src/dbus/qdbusconnectioninterface.cpp
changeset 0 1918ee327afb
child 3 41300fa6a67c
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the QtDBus module of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    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.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 #include "qdbusconnectioninterface.h"
       
    43 
       
    44 #include <QtCore/QByteArray>
       
    45 #include <QtCore/QList>
       
    46 #include <QtCore/QMap>
       
    47 #include <QtCore/QString>
       
    48 #include <QtCore/QStringList>
       
    49 #include <QtCore/QVariant>
       
    50 #include <QtCore/QDebug>
       
    51 
       
    52 #include <qdbus_symbols_p.h>          // for the DBUS_* constants
       
    53 
       
    54 QT_BEGIN_NAMESPACE
       
    55 
       
    56 /*
       
    57  * Implementation of interface class QDBusConnectionInterface
       
    58  */
       
    59 
       
    60 /*!
       
    61     \class QDBusConnectionInterface
       
    62     \inmodule QtDBus
       
    63     \since 4.2
       
    64 
       
    65     \brief The QDBusConnectionInterface class provides access to the D-Bus bus daemon service.
       
    66 
       
    67     The D-Bus bus server daemon provides one special interface \c
       
    68     org.freedesktop.DBus that allows clients to access certain
       
    69     properties of the bus, such as the current list of clients
       
    70     connected. The QDBusConnectionInterface class provides access to that
       
    71     interface.
       
    72 
       
    73     The most common uses of this class are to register and unregister
       
    74     service names on the bus using the registerService() and
       
    75     unregisterService() functions, query about existing names using
       
    76     the isServiceRegistered(), registeredServiceNames() and
       
    77     serviceOwner() functions, and to receive notification that a
       
    78     client has registered or de-registered through the
       
    79     serviceRegistered(), serviceUnregistered() and serviceOwnerChanged()
       
    80     signals.
       
    81 */
       
    82 
       
    83 /*!
       
    84     \enum QDBusConnectionInterface::ServiceQueueOptions
       
    85 
       
    86     Flags for determining how a service registration should behave, in
       
    87     case the service name is already registered.
       
    88 
       
    89     \value DontQueueService     If an application requests a name that
       
    90                                 is already owned, no queueing will be
       
    91                                 performed. The registeredService()
       
    92                                 call will simply fail.
       
    93                                 This is the default.
       
    94 
       
    95     \value QueueService         Attempts to register the requested
       
    96                                 service, but do not try to replace it
       
    97                                 if another application already has it
       
    98                                 registered. Instead, simply put this
       
    99                                 application in queue, until it is
       
   100                                 given up. The serviceRegistered()
       
   101                                 signal will be emitted when that
       
   102                                 happens.
       
   103 
       
   104     \value ReplaceExistingService If another application already has
       
   105                                 the service name registered, attempt
       
   106                                 to replace it.
       
   107 
       
   108     \sa ServiceReplacementOptions
       
   109 */
       
   110 
       
   111 /*!
       
   112     \enum QDBusConnectionInterface::ServiceReplacementOptions
       
   113 
       
   114     Flags for determining if the D-Bus server should allow another
       
   115     application to replace a name that this application has registered
       
   116     with the ReplaceExistingService option.
       
   117 
       
   118     The possible values are:
       
   119 
       
   120     \value DontAllowReplacement Do not allow another application to
       
   121                                 replace us. The service must be
       
   122                                 explicitly unregistered with
       
   123                                 unregisterService() for another
       
   124                                 application to acquire it.
       
   125                                 This is the default.
       
   126 
       
   127     \value AllowReplacement     Allow other applications to replace us
       
   128                                 with the ReplaceExistingService option
       
   129                                 to registerService() without
       
   130                                 intervention. If that happens, the
       
   131                                 serviceUnregistered() signal will be
       
   132                                 emitted.
       
   133 
       
   134     \sa ServiceQueueOptions
       
   135 */
       
   136 
       
   137 /*!
       
   138     \enum QDBusConnectionInterface::RegisterServiceReply
       
   139 
       
   140     The possible return values from registerService():
       
   141 
       
   142     \value ServiceNotRegistered The call failed and the service name was not registered.
       
   143     \value ServiceRegistered    The caller is now the owner of the service name.
       
   144     \value ServiceQueued        The caller specified the QueueService flag and the
       
   145                                 service was already registered, so we are in queue.
       
   146 
       
   147     The serviceRegistered() signal will be emitted when the service is
       
   148     acquired by this application.
       
   149 */
       
   150 
       
   151 /*!
       
   152     \internal
       
   153 */
       
   154 const char *QDBusConnectionInterface::staticInterfaceName()
       
   155 { return "org.freedesktop.DBus"; }
       
   156 
       
   157 /*!
       
   158     \internal
       
   159 */
       
   160 QDBusConnectionInterface::QDBusConnectionInterface(const QDBusConnection &connection,
       
   161                                                    QObject *parent)
       
   162     : QDBusAbstractInterface(QLatin1String(DBUS_SERVICE_DBUS),
       
   163                              QLatin1String(DBUS_PATH_DBUS),
       
   164                              DBUS_INTERFACE_DBUS, connection, parent)
       
   165 {
       
   166     connect(this, SIGNAL(NameAcquired(QString)), this, SIGNAL(serviceRegistered(QString)));
       
   167     connect(this, SIGNAL(NameLost(QString)), this, SIGNAL(serviceUnregistered(QString)));
       
   168     connect(this, SIGNAL(NameOwnerChanged(QString,QString,QString)),
       
   169             this, SIGNAL(serviceOwnerChanged(QString,QString,QString)));
       
   170 }
       
   171 
       
   172 /*!
       
   173     \internal
       
   174 */
       
   175 QDBusConnectionInterface::~QDBusConnectionInterface()
       
   176 {
       
   177 }
       
   178 
       
   179 /*!
       
   180     Returns the unique connection name of the primary owner of the
       
   181     name \a name. If the requested name doesn't have an owner, returns
       
   182     a \c org.freedesktop.DBus.Error.NameHasNoOwner error.
       
   183 */
       
   184 QDBusReply<QString> QDBusConnectionInterface::serviceOwner(const QString &name) const
       
   185 {
       
   186     return internalConstCall(QDBus::AutoDetect, QLatin1String("GetNameOwner"), QList<QVariant>() << name);
       
   187 }
       
   188 
       
   189 /*!
       
   190   \property QDBusConnectionInterface::registeredServiceNames
       
   191   \brief holds the registered service names
       
   192 
       
   193   Lists all names currently registered on the bus.
       
   194 */
       
   195 QDBusReply<QStringList> QDBusConnectionInterface::registeredServiceNames() const
       
   196 {
       
   197     return internalConstCall(QDBus::AutoDetect, QLatin1String("ListNames"));
       
   198 }
       
   199 
       
   200 /*!
       
   201     Returns true if the service name \a serviceName has is currently
       
   202     registered.
       
   203 */
       
   204 QDBusReply<bool> QDBusConnectionInterface::isServiceRegistered(const QString &serviceName) const
       
   205 {
       
   206     return internalConstCall(QDBus::AutoDetect, QLatin1String("NameHasOwner"),
       
   207                              QList<QVariant>() << serviceName);
       
   208 }
       
   209 
       
   210 /*!
       
   211     Returns the Unix Process ID (PID) for the process currently
       
   212     holding the bus service \a serviceName.
       
   213 */
       
   214 QDBusReply<uint> QDBusConnectionInterface::servicePid(const QString &serviceName) const
       
   215 {
       
   216     return internalConstCall(QDBus::AutoDetect, QLatin1String("GetConnectionUnixProcessID"),
       
   217                              QList<QVariant>() << serviceName);
       
   218 }
       
   219 
       
   220 /*!
       
   221     Returns the Unix User ID (UID) for the process currently holding
       
   222     the bus service \a serviceName.
       
   223 */
       
   224 QDBusReply<uint> QDBusConnectionInterface::serviceUid(const QString &serviceName) const
       
   225 {
       
   226     return internalConstCall(QDBus::AutoDetect, QLatin1String("GetConnectionUnixUser"),
       
   227                              QList<QVariant>() << serviceName);
       
   228 }
       
   229 
       
   230 /*!
       
   231     Requests that the bus start the service given by the name \a name.
       
   232 */
       
   233 QDBusReply<void> QDBusConnectionInterface::startService(const QString &name)
       
   234 {
       
   235     return call(QLatin1String("StartServiceByName"), name, uint(0));
       
   236 }
       
   237 
       
   238 /*!
       
   239     Requests to register the service name \a serviceName on the
       
   240     bus. The \a qoption flag specifies how the D-Bus server should behave
       
   241     if \a serviceName is already registered. The \a roption flag
       
   242     specifies if the server should allow another application to
       
   243     replace our registered name.
       
   244 
       
   245     If the service registration succeeds, the serviceRegistered()
       
   246     signal will be emitted. If we are placed in queue, the signal will
       
   247     be emitted when we obtain the name. If \a roption is
       
   248     AllowReplacement, the serviceUnregistered() signal will be emitted
       
   249     if another application replaces this one.
       
   250 
       
   251     \sa unregisterService()
       
   252 */
       
   253 QDBusReply<QDBusConnectionInterface::RegisterServiceReply>
       
   254 QDBusConnectionInterface::registerService(const QString &serviceName,
       
   255                                           ServiceQueueOptions qoption,
       
   256                                           ServiceReplacementOptions roption)
       
   257 {
       
   258     // reconstruct the low-level flags
       
   259     uint flags = 0;
       
   260     switch (qoption) {
       
   261     case DontQueueService:
       
   262         flags = DBUS_NAME_FLAG_DO_NOT_QUEUE;
       
   263         break;
       
   264     case QueueService:
       
   265         flags = 0;
       
   266         break;
       
   267     case ReplaceExistingService:
       
   268         flags = DBUS_NAME_FLAG_DO_NOT_QUEUE | DBUS_NAME_FLAG_REPLACE_EXISTING;
       
   269         break;
       
   270     }
       
   271 
       
   272     switch (roption) {
       
   273     case DontAllowReplacement:
       
   274         break;
       
   275     case AllowReplacement:
       
   276         flags |= DBUS_NAME_FLAG_ALLOW_REPLACEMENT;
       
   277         break;
       
   278     }
       
   279 
       
   280     QDBusMessage reply = call(QLatin1String("RequestName"), serviceName, flags);
       
   281 //    qDebug() << "QDBusConnectionInterface::registerService" << serviceName << "Reply:" << reply;
       
   282 
       
   283     // convert the low-level flags to something that we can use
       
   284     if (reply.type() == QDBusMessage::ReplyMessage) {
       
   285         uint code = 0;
       
   286 
       
   287         switch (reply.arguments().at(0).toUInt()) {
       
   288         case DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER:
       
   289         case DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER:
       
   290             code = uint(ServiceRegistered);
       
   291             break;
       
   292 
       
   293         case DBUS_REQUEST_NAME_REPLY_EXISTS:
       
   294             code = uint(ServiceNotRegistered);
       
   295             break;
       
   296 
       
   297         case DBUS_REQUEST_NAME_REPLY_IN_QUEUE:
       
   298             code = uint(ServiceQueued);
       
   299             break;
       
   300         }
       
   301 
       
   302         reply.setArguments(QVariantList() << code);
       
   303     }
       
   304 
       
   305     return reply;
       
   306 }
       
   307 
       
   308 /*!
       
   309     Releases the claim on the bus service name \a serviceName, that
       
   310     had been previously registered with registerService(). If this
       
   311     application had ownership of the name, it will be released for
       
   312     other applications to claim. If it only had the name queued, it
       
   313     gives up its position in the queue.
       
   314 */
       
   315 QDBusReply<bool>
       
   316 QDBusConnectionInterface::unregisterService(const QString &serviceName)
       
   317 {
       
   318     QDBusMessage reply = call(QLatin1String("ReleaseName"), serviceName);
       
   319     if (reply.type() == QDBusMessage::ReplyMessage) {
       
   320         bool success = reply.arguments().at(0).toUInt() == DBUS_RELEASE_NAME_REPLY_RELEASED;
       
   321         reply.setArguments(QVariantList() << success);
       
   322     }
       
   323     return reply;
       
   324 }
       
   325 
       
   326 /*!
       
   327     \internal
       
   328 */
       
   329 void QDBusConnectionInterface::connectNotify(const char *signalName)
       
   330 {
       
   331     // translate the signal names to what we really want
       
   332     // this avoids setting hooks for signals that don't exist on the bus
       
   333     if (qstrcmp(signalName, SIGNAL(serviceRegistered(QString))) == 0)
       
   334         QDBusAbstractInterface::connectNotify(SIGNAL(NameAcquired(QString)));
       
   335 
       
   336     else if (qstrcmp(signalName, SIGNAL(serviceUnregistered(QString))) == 0)
       
   337         QDBusAbstractInterface::connectNotify(SIGNAL(NameLost(QString)));
       
   338 
       
   339     else if (qstrcmp(signalName, SIGNAL(serviceOwnerChanged(QString,QString,QString))) == 0)
       
   340         QDBusAbstractInterface::connectNotify(SIGNAL(NameOwnerChanged(QString,QString,QString)));
       
   341 }
       
   342 
       
   343 /*!
       
   344     \internal
       
   345 */
       
   346 void QDBusConnectionInterface::disconnectNotify(const char *signalName)
       
   347 {
       
   348     // translate the signal names to what we really want
       
   349     // this avoids setting hooks for signals that don't exist on the bus
       
   350     if (qstrcmp(signalName, SIGNAL(serviceRegistered(QString))) == 0)
       
   351         QDBusAbstractInterface::disconnectNotify(SIGNAL(NameAcquired(QString)));
       
   352 
       
   353     else if (qstrcmp(signalName, SIGNAL(serviceUnregistered(QString))) == 0)
       
   354         QDBusAbstractInterface::disconnectNotify(SIGNAL(NameLost(QString)));
       
   355 
       
   356     else if (qstrcmp(signalName, SIGNAL(serviceOwnerChanged(QString,QString,QString))) == 0)
       
   357         QDBusAbstractInterface::disconnectNotify(SIGNAL(NameOwnerChanged(QString,QString,QString)));
       
   358 }
       
   359 
       
   360 // signals
       
   361 /*!
       
   362     \fn QDBusConnectionInterface::serviceRegistered(const QString &serviceName)
       
   363 
       
   364     This signal is emitted by the D-Bus server when the bus service
       
   365     name (unique connection name or well-known service name) given by
       
   366     \a serviceName is acquired by this application.
       
   367 
       
   368     Acquisition happens after this application has requested a name using
       
   369     registerService().
       
   370 */
       
   371 
       
   372 /*!
       
   373     \fn QDBusConnectionInterface::serviceUnregistered(const QString &serviceName)
       
   374 
       
   375     This signal is emitted by the D-Bus server when this application
       
   376     loses ownership of the bus service name given by \a serviceName.
       
   377 */
       
   378 
       
   379 /*!
       
   380     \fn QDBusConnectionInterface::serviceOwnerChanged(const QString &name, const QString &oldOwner, const QString &newOwner)
       
   381 
       
   382     This signal is emitted by the D-Bus server whenever a service
       
   383     ownership change happens in the bus, including apparition and
       
   384     disparition of names.
       
   385 
       
   386     This signal means the application \a oldOwner lost ownership of
       
   387     bus name \a name to application \a newOwner. If \a oldOwner is an
       
   388     empty string, it means the name \a name has just been created; if
       
   389     \a newOwner is empty, the name \a name has no current owner and is
       
   390     no longer available.
       
   391 */
       
   392 
       
   393 /*!
       
   394   \fn void QDBusConnectionInterface::callWithCallbackFailed(const QDBusError &error, const QDBusMessage &call)
       
   395 
       
   396   This signal is emitted when there is an error during a
       
   397   QDBusConnection::callWithCallback(). \a error specifies the error.
       
   398   \a call is the message that couldn't be delivered.
       
   399 
       
   400   \sa QDBusConnection::callWithCallback()
       
   401  */
       
   402 
       
   403 QT_END_NAMESPACE