summaryrefslogtreecommitdiff
path: root/TelepathyQt/dbus-service.cpp
blob: fa3936353a3e57482ce7d544808e7a2d8a83f585 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
/**
 * This file is part of TelepathyQt
 *
 * @copyright Copyright (C) 2012 Collabora Ltd. <http://www.collabora.co.uk/>
 * @copyright Copyright (C) 2012 Nokia Corporation
 * @license LGPL 2.1
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include <TelepathyQt/DBusService>

#include "TelepathyQt/_gen/dbus-service.moc.hpp"

#include "TelepathyQt/debug-internal.h"

#include <TelepathyQt/Constants>
#include <TelepathyQt/DBusObject>

#include <QDBusConnection>
#include <QString>

namespace Tp
{

struct TP_QT_NO_EXPORT DBusService::Private
{
    Private(DBusService *parent, const QDBusConnection &dbusConnection)
        : parent(parent),
          dbusObject(new DBusObject(dbusConnection, parent)),
          registered(false)
    {
    }

    DBusService *parent;
    QString busName;
    DBusObject *dbusObject;
    bool registered;
};

/**
 * \class DBusService
 * \ingroup servicesideimpl
 * \headerfile TelepathyQt/dbus-service.h <TelepathyQt/DBusService>
 *
 * \brief Base class for D-Bus services.
 *
 * This class serves as a base for all the classes that are used to implement
 * D-Bus services.
 */

/**
 * Construct a DBusService that uses the given \a dbusConnection.
 *
 * \param dbusConnection The D-Bus connection that will be used by this service.
 */
DBusService::DBusService(const QDBusConnection &dbusConnection)
    : mPriv(new Private(this, dbusConnection))
{
}

/**
 * Class destructor.
 */
DBusService::~DBusService()
{
    delete mPriv;
}

/**
 * Return the D-Bus connection associated with this service.
 *
 * \return the D-Bus connection associated with this service.
 */
QDBusConnection DBusService::dbusConnection() const
{
    return mPriv->dbusObject->dbusConnection();
}

/**
 * Return the D-Bus service name of this service.
 *
 * This is only valid after this service has been registered
 * on the bus using registerObject().
 *
 * \return the D-Bus service name of this service.
 */
QString DBusService::busName() const
{
    return mPriv->busName;
}

/**
 * Return the D-Bus object path of this service.
 *
 * This is only valid after this service has been registered
 * on the bus using registerObject().
 *
 * \return the D-Bus object path of this service.
 */
QString DBusService::objectPath() const
{
    return mPriv->dbusObject->objectPath();
}

/**
 * Return the DBusObject that is used for registering this service on the bus.
 *
 * The DBusObject is the object on which all the interface adaptors
 * for this service are plugged.
 *
 * \return a pointer to the DBusObject that is used for registering
 * this service on the bus.
 */
DBusObject *DBusService::dbusObject() const
{
    return mPriv->dbusObject;
}

/**
 * Return whether this D-Bus service has been registered on the bus or not.
 *
 * \return \c true if the service has been registered, or \c false otherwise.
 */
bool DBusService::isRegistered() const
{
    return mPriv->registered;
}

/**
 * Register this service object on the bus with the given \a busName and \a objectPath.
 *
 * \a error needs to be a valid pointer to a DBusError instance, where any
 * possible D-Bus error will be stored.
 *
 * A service may only be registered once in its lifetime.
 * Use isRegistered() to find out if it has already been registered or not.
 *
 * You normally don't need to use this method directly.
 * Subclasses should provide a simplified version of it.
 *
 * \param busName The D-Bus service name of this object.
 * \param objectPath The D-Bus object path of this object.
 * \param error A pointer to a valid DBusError instance, where any
 * possible D-Bus error will be stored.
 * \return \c true on success or \c false otherwise.
 */
bool DBusService::registerObject(const QString &busName, const QString &objectPath,
        DBusError *error)
{
    if (mPriv->registered) {
        return true;
    }

    if (!mPriv->dbusObject->dbusConnection().registerObject(objectPath, mPriv->dbusObject)) {
        error->set(TP_QT_ERROR_INVALID_ARGUMENT,
                QString(QLatin1String("Object at path %1 already registered"))
                    .arg(objectPath));
        warning() << "Unable to register object" << objectPath <<
            "- path already registered";
        return false;
    }

    if (!mPriv->dbusObject->dbusConnection().registerService(busName)) {
        mPriv->dbusObject->dbusConnection().unregisterObject(objectPath);
        error->set(TP_QT_ERROR_INVALID_ARGUMENT,
                QString(QLatin1String("Name %1 already in use by another process"))
                    .arg(busName));
        warning() << "Unable to register service" << busName <<
            "- name already registered by another process";
        return false;
    }

    debug() << "Registered object" << objectPath << "at bus name" << busName;

    mPriv->busName = busName;
    mPriv->dbusObject->setObjectPath(objectPath);
    mPriv->registered = true;
    return true;
}

/**
 * \fn QVariantMap DBusService::immutableProperties() const
 *
 * Return the immutable properties of this D-Bus service object.
 *
 * Immutable properties cannot change after the object has been registered
 * on the bus with registerObject().
 *
 * \return The immutable properties of this D-Bus service object.
 */

struct AbstractDBusServiceInterface::Private
{
    Private(const QString &interfaceName)
        : interfaceName(interfaceName),
          dbusObject(0),
          registered(false)
    {
    }

    QString interfaceName;
    DBusObject *dbusObject;
    bool registered;
};

/**
 * \class AbstractDBusServiceInterface
 * \ingroup servicesideimpl
 * \headerfile TelepathyQt/dbus-service.h <TelepathyQt/AbstractDBusServiceInterface>
 *
 * \brief Base class for D-Bus service interfaces.
 *
 * This class serves as a base for all the classes that are used to implement
 * interfaces that sit on top of D-Bus services.
 */

/**
 * Construct an AbstractDBusServiceInterface that implements
 * the interface with the given \a interfaceName.
 *
 * \param interfaceName The name of the interface that this class implements.
 */
AbstractDBusServiceInterface::AbstractDBusServiceInterface(const QString &interfaceName)
    : mPriv(new Private(interfaceName))
{
}

/**
 * Class destructor.
 */
AbstractDBusServiceInterface::~AbstractDBusServiceInterface()
{
    delete mPriv;
}

/**
 * Return the name of the interface that this class implements,
 * as given on the constructor.
 *
 * \return The name of the interface that this class implements.
 */
QString AbstractDBusServiceInterface::interfaceName() const
{
    return mPriv->interfaceName;
}

/**
 * Return the DBusObject on which the adaptor of this interface is plugged.
 *
 * This is only accessible after the interface has been registered
 * with registerInterface().
 *
 * \return a pointer to the DBusObject on which the adaptor
 * of this interface is plugged.
 * \sa DBusService::dbusObject()
 */
DBusObject *AbstractDBusServiceInterface::dbusObject() const
{
    return mPriv->dbusObject;
}

/**
 * Return whether this interface has been registered.
 *
 * \return \c true if the service has been registered, or \c false otherwise.
 * \sa registerInterface()
 */
bool AbstractDBusServiceInterface::isRegistered() const
{
    return mPriv->registered;
}

/**
 * Emit PropertiesChanged signal on object org.freedesktop.DBus.Properties interface
 * with the property \a propertyName.
 *
 * \param propertyName The name of the changed property.
 * \param propertyValue The actual value of the changed property.
 * \return \c false if the signal can not be emmited or \a true otherwise.
 */
bool AbstractDBusServiceInterface::notifyPropertyChanged(const QString &propertyName, const QVariant &propertyValue)
{
    if (!isRegistered()) {
        return false;
    }

    QDBusMessage signal = QDBusMessage::createSignal(dbusObject()->objectPath(),
                                                     TP_QT_IFACE_PROPERTIES,
                                                     QLatin1String("PropertiesChanged"));
    QVariantMap changedProperties;
    changedProperties.insert(propertyName, propertyValue);

    signal << interfaceName();
    signal << changedProperties;
    signal << QStringList();

    return dbusObject()->dbusConnection().send(signal);
}

/**
 * Registers this interface by plugging its adaptor
 * on the given \a dbusObject.
 *
 * \param dbusObject The object on which to plug the adaptor.
 * \return \c false if the interface has already been registered,
 * or \a true otherwise.
 * \sa isRegistered()
 */
bool AbstractDBusServiceInterface::registerInterface(DBusObject *dbusObject)
{
    if (mPriv->registered) {
        return true;
    }

    mPriv->dbusObject = dbusObject;
    createAdaptor();
    mPriv->registered = true;
    return true;
}

/**
 * \fn QVariantMap AbstractDBusServiceInterface::immutableProperties() const
 *
 * Return the immutable properties of this interface.
 *
 * Immutable properties cannot change after the interface has been registered
 * on a service on the bus with registerInterface().
 *
 * \return The immutable properties of this interface.
 */

/**
 * \fn void AbstractDBusServiceInterface::createAdaptor()
 *
 * Create the adaptor for this interface.
 *
 * Subclasses should reimplement this appropriately.
 */

}