source: trunk/src/dbus/qdbusconnectioninterface.cpp@ 603

Last change on this file since 603 was 561, checked in by Dmitry A. Kuminov, 15 years ago

trunk: Merged in qt 4.6.1 sources.

File size: 15.3 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation ([email protected])
6**
7** This file is part of the QtDBus module of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
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** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you have questions regarding the use of this file, please contact
37** Nokia at [email protected].
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
54QT_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*/
154const char *QDBusConnectionInterface::staticInterfaceName()
155{ return "org.freedesktop.DBus"; }
156
157/*!
158 \internal
159*/
160QDBusConnectionInterface::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*/
175QDBusConnectionInterface::~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*/
184QDBusReply<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*/
195QDBusReply<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*/
204QDBusReply<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*/
214QDBusReply<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*/
224QDBusReply<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*/
233QDBusReply<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*/
253QDBusReply<QDBusConnectionInterface::RegisterServiceReply>
254QDBusConnectionInterface::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*/
315QDBusReply<bool>
316QDBusConnectionInterface::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*/
329void 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 static bool warningPrinted = false;
341 if (!warningPrinted) {
342 qWarning("Connecting to deprecated signal QDBusConnectionInterface::serviceOwnerChanged(QString,QString,QString)");
343 warningPrinted = true;
344 }
345 QDBusAbstractInterface::connectNotify(SIGNAL(NameOwnerChanged(QString,QString,QString)));
346 }
347}
348
349/*!
350 \internal
351*/
352void QDBusConnectionInterface::disconnectNotify(const char *signalName)
353{
354 // translate the signal names to what we really want
355 // this avoids setting hooks for signals that don't exist on the bus
356 if (qstrcmp(signalName, SIGNAL(serviceRegistered(QString))) == 0)
357 QDBusAbstractInterface::disconnectNotify(SIGNAL(NameAcquired(QString)));
358
359 else if (qstrcmp(signalName, SIGNAL(serviceUnregistered(QString))) == 0)
360 QDBusAbstractInterface::disconnectNotify(SIGNAL(NameLost(QString)));
361
362 else if (qstrcmp(signalName, SIGNAL(serviceOwnerChanged(QString,QString,QString))) == 0)
363 QDBusAbstractInterface::disconnectNotify(SIGNAL(NameOwnerChanged(QString,QString,QString)));
364}
365
366// signals
367/*!
368 \fn QDBusConnectionInterface::serviceRegistered(const QString &serviceName)
369
370 This signal is emitted by the D-Bus server when the bus service
371 name (unique connection name or well-known service name) given by
372 \a serviceName is acquired by this application.
373
374 Acquisition happens after this application has requested a name using
375 registerService().
376*/
377
378/*!
379 \fn QDBusConnectionInterface::serviceUnregistered(const QString &serviceName)
380
381 This signal is emitted by the D-Bus server when this application
382 loses ownership of the bus service name given by \a serviceName.
383*/
384
385/*!
386 \fn QDBusConnectionInterface::serviceOwnerChanged(const QString &name, const QString &oldOwner, const QString &newOwner)
387
388 This signal is emitted by the D-Bus server whenever a service
389 ownership change happens in the bus, including apparition and
390 disparition of names.
391
392 This signal means the application \a oldOwner lost ownership of
393 bus name \a name to application \a newOwner. If \a oldOwner is an
394 empty string, it means the name \a name has just been created; if
395 \a newOwner is empty, the name \a name has no current owner and is
396 no longer available.
397
398 \note connecting to this signal will make the application listen for and
399 receive every single service ownership change on the bus. Depending on
400 how many services are running, this make the application be activated to
401 receive more signals than it needs. To avoid this problem, use the
402 QDBusServiceWatcher class, which can listen for specific changes.
403*/
404
405/*!
406 \fn void QDBusConnectionInterface::callWithCallbackFailed(const QDBusError &error, const QDBusMessage &call)
407
408 This signal is emitted when there is an error during a
409 QDBusConnection::callWithCallback(). \a error specifies the error.
410 \a call is the message that couldn't be delivered.
411
412 \sa QDBusConnection::callWithCallback()
413 */
414
415QT_END_NAMESPACE
Note: See TracBrowser for help on using the repository browser.