source: trunk/src/dbus/qdbusconnection.cpp@ 807

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

trunk: Merged in qt 4.6.3 sources from branches/vendor/nokia/qt.

File size: 37.0 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2010 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 <qdebug.h>
43#include <qcoreapplication.h>
44#include <qstringlist.h>
45
46#include "qdbusconnection.h"
47#include "qdbusconnectioninterface.h"
48#include "qdbuserror.h"
49#include "qdbusmessage.h"
50#include "qdbusmessage_p.h"
51#include "qdbusconnection_p.h"
52#include "qdbusinterface_p.h"
53#include "qdbusutil_p.h"
54
55#include "qdbusthreaddebug_p.h"
56
57QT_BEGIN_NAMESPACE
58
59class QDBusConnectionManager
60{
61public:
62 QDBusConnectionManager() {}
63 ~QDBusConnectionManager();
64
65 QDBusConnectionPrivate *connection(const QString &name) const;
66 void removeConnection(const QString &name);
67 void setConnection(const QString &name, QDBusConnectionPrivate *c);
68
69 QDBusConnectionPrivate *sender() const;
70 void setSender(const QDBusConnectionPrivate *s);
71
72 mutable QMutex mutex;
73private:
74 QHash<QString, QDBusConnectionPrivate *> connectionHash;
75
76 mutable QMutex senderMutex;
77 QString senderName; // internal; will probably change
78};
79
80Q_GLOBAL_STATIC(QDBusConnectionManager, _q_manager)
81
82QDBusConnectionPrivate *QDBusConnectionManager::sender() const
83{
84 QMutexLocker locker(&senderMutex);
85 return connection(senderName);
86}
87
88void QDBusConnectionManager::setSender(const QDBusConnectionPrivate *s)
89{
90 QMutexLocker locker(&senderMutex);
91 senderName = (s ? s->name : QString());
92}
93
94QDBusConnectionPrivate *QDBusConnectionManager::connection(const QString &name) const
95{
96 return connectionHash.value(name, 0);
97}
98
99void QDBusConnectionManager::removeConnection(const QString &name)
100{
101 QDBusConnectionPrivate *d = 0;
102 d = connectionHash.take(name);
103 if (d && !d->ref.deref())
104 d->deleteYourself();
105
106 // Static objects may be keeping the connection open.
107 // However, it is harmless to have outstanding references to a connection that is
108 // closing as long as those references will be soon dropped without being used.
109
110 // ### Output a warning if connections are being used after they have been removed.
111}
112
113QDBusConnectionManager::~QDBusConnectionManager()
114{
115 for (QHash<QString, QDBusConnectionPrivate *>::const_iterator it = connectionHash.constBegin();
116 it != connectionHash.constEnd(); ++it) {
117 QDBusConnectionPrivate *d = it.value();
118 if (!d->ref.deref())
119 d->deleteYourself();
120 else
121 d->closeConnection();
122 }
123 connectionHash.clear();
124}
125
126QDBUS_EXPORT void qDBusBindToApplication();
127void qDBusBindToApplication()
128{
129}
130
131void QDBusConnectionManager::setConnection(const QString &name, QDBusConnectionPrivate *c)
132{
133 connectionHash[name] = c;
134 c->name = name;
135}
136
137/*!
138 \fn QDBusConnection &QDBusConnection::sessionBus()
139 \relates QDBusConnection
140
141 Returns a QDBusConnection object opened with the session bus. The object reference returned
142 by this function is valid until the QCoreApplication's destructor is run, when the
143 connection will be closed and the object, deleted.
144*/
145/*!
146 \fn QDBusConnection &QDBusConnection::systemBus()
147 \relates QDBusConnection
148
149 Returns a QDBusConnection object opened with the system bus. The object reference returned
150 by this function is valid until the QCoreApplication's destructor is run, when the
151 connection will be closed and the object, deleted.
152*/
153
154/*!
155 \class QDBusConnection
156 \inmodule QtDBus
157 \since 4.2
158
159 \brief The QDBusConnection class represents a connection to the D-Bus bus daemon.
160
161 This class is the initial point in a D-Bus session. Using it, you
162 can get access to remote objects, interfaces; connect remote
163 signals to your object's slots; register objects, etc.
164
165 D-Bus connections are created using the connectToBus() function,
166 which opens a connection to the server daemon and does the initial
167 handshaking, associating that connection with a name. Further
168 attempts to connect using the same name will return the same
169 connection.
170
171 The connection is then torn down using the disconnectFromBus()
172 function.
173
174 As a convenience for the two most common connection types, the
175 sessionBus() and systemBus() functions return open connections to
176 the session server daemon and the system server daemon,
177 respectively. Those connections are opened when first used and are
178 closed when the QCoreApplication destructor is run.
179
180 D-Bus also supports peer-to-peer connections, without the need for
181 a bus server daemon. Using this facility, two applications can
182 talk to each other and exchange messages. This can be achieved by
183 passing an address to connectToBus() function, which was opened by
184 another D-Bus application using QDBusServer.
185*/
186
187/*!
188 \enum QDBusConnection::BusType
189 Specifies the type of the bus connection. The valid bus types are:
190
191 \value SessionBus the session bus, associated with the running desktop session
192 \value SystemBus the system bus, used to communicate with system-wide processes
193 \value ActivationBus the activation bus, the "alias" for the bus that started the
194 service
195
196 On the Session Bus, one can find other applications by the same user that are sharing the same
197 desktop session (hence the name). On the System Bus, however, processes shared for the whole
198 system are usually found.
199*/
200
201/*!
202 \enum QDBusConnection::RegisterOption
203 Specifies the options for registering objects with the connection. The possible values are:
204
205 \value ExportAdaptors export the contents of adaptors found in this object
206
207 \value ExportScriptableSlots export this object's scriptable slots
208 \value ExportScriptableSignals export this object's scriptable signals
209 \value ExportScriptableProperties export this object's scriptable properties
210 \value ExportScriptableContents shorthand form for ExportScriptableSlots |
211 ExportScriptableSignals |
212 ExportScriptableProperties
213
214 \value ExportNonScriptableSlots export this object's non-scriptable slots
215 \value ExportNonScriptableSignals export this object's non-scriptable signals
216 \value ExportNonScriptableProperties export this object's non-scriptable properties
217 \value ExportNonScriptableContents shorthand form for ExportNonScriptableSlots |
218 ExportNonScriptableSignals |
219 ExportNonScriptableProperties
220
221 \value ExportAllSlots export all of this object's slots
222 \value ExportAllSignals export all of this object's signals
223 \value ExportAllProperties export all of this object's properties
224 \value ExportAllContents export all of this object's contents
225
226 \value ExportChildObjects export this object's child objects
227
228 \sa registerObject(), QDBusAbstractAdaptor, {usingadaptors.html}{Using adaptors}
229*/
230
231/*!
232 \enum QDBusConnection::UnregisterMode
233 The mode for unregistering an object path:
234
235 \value UnregisterNode unregister this node only: do not unregister child objects
236 \value UnregisterTree unregister this node and all its sub-tree
237
238 Note, however, if this object was registered with the ExportChildObjects option, UnregisterNode
239 will unregister the child objects too.
240*/
241
242/*!
243 Creates a QDBusConnection object attached to the connection with name \a name.
244
245 This does not open the connection. You have to call connectToBus() to open it.
246*/
247QDBusConnection::QDBusConnection(const QString &name)
248{
249 if (name.isEmpty()) {
250 d = 0;
251 } else {
252 QMutexLocker locker(&_q_manager()->mutex);
253 d = _q_manager()->connection(name);
254 if (d)
255 d->ref.ref();
256 }
257}
258
259/*!
260 Creates a copy of the \a other connection.
261*/
262QDBusConnection::QDBusConnection(const QDBusConnection &other)
263{
264 d = other.d;
265 if (d)
266 d->ref.ref();
267}
268
269/*!
270 \internal
271 Creates a connection object with the given \a dd as private object.
272*/
273QDBusConnection::QDBusConnection(QDBusConnectionPrivate *dd)
274{
275 d = dd;
276 if (d)
277 d->ref.ref();
278}
279
280/*!
281 Disposes of this object. This does not close the connection: you
282 have to call disconnectFromBus() to do that.
283*/
284QDBusConnection::~QDBusConnection()
285{
286 if (d && !d->ref.deref())
287 d->deleteYourself();
288}
289
290/*!
291 Creates a copy of the connection \a other in this object. Note
292 that the connection this object referenced before the copy, is not
293 spontaneously disconnected.
294
295 \sa disconnectFromBus()
296*/
297QDBusConnection &QDBusConnection::operator=(const QDBusConnection &other)
298{
299 if (other.d)
300 other.d->ref.ref();
301 if (d && !d->ref.deref())
302 d->deleteYourself();
303 d = other.d;
304 return *this;
305}
306
307/*!
308 Opens a connection of type \a type to one of the known busses and
309 associate with it the connection name \a name. Returns a
310 QDBusConnection object associated with that connection.
311*/
312QDBusConnection QDBusConnection::connectToBus(BusType type, const QString &name)
313{
314// Q_ASSERT_X(QCoreApplication::instance(), "QDBusConnection::addConnection",
315// "Cannot create connection without a Q[Core]Application instance");
316 if (!qdbus_loadLibDBus()) {
317 QDBusConnectionPrivate *d = 0;
318 return QDBusConnection(d);
319 }
320
321 QMutexLocker locker(&_q_manager()->mutex);
322
323 QDBusConnectionPrivate *d = _q_manager()->connection(name);
324 if (d || name.isEmpty())
325 return QDBusConnection(d);
326
327 d = new QDBusConnectionPrivate;
328 DBusConnection *c = 0;
329 QDBusErrorInternal error;
330 switch (type) {
331 case SystemBus:
332 c = q_dbus_bus_get_private(DBUS_BUS_SYSTEM, error);
333 break;
334 case SessionBus:
335 c = q_dbus_bus_get_private(DBUS_BUS_SESSION, error);
336 break;
337 case ActivationBus:
338 c = q_dbus_bus_get_private(DBUS_BUS_STARTER, error);
339 break;
340 }
341 d->setConnection(c, error); //setConnection does the error handling for us
342
343 _q_manager()->setConnection(name, d);
344
345 QDBusConnection retval(d);
346
347 // create the bus service
348 // will lock in QDBusConnectionPrivate::connectRelay()
349 d->setBusService(retval);
350
351 return retval;
352}
353
354/*!
355 Opens a peer-to-peer connection on address \a address and associate with it the
356 connection name \a name. Returns a QDBusConnection object associated with that connection.
357*/
358QDBusConnection QDBusConnection::connectToBus(const QString &address,
359 const QString &name)
360{
361// Q_ASSERT_X(QCoreApplication::instance(), "QDBusConnection::addConnection",
362// "Cannot create connection without a Q[Core]Application instance");
363 if (!qdbus_loadLibDBus()){
364 QDBusConnectionPrivate *d = 0;
365 return QDBusConnection(d);
366 }
367
368 QMutexLocker locker(&_q_manager()->mutex);
369
370 QDBusConnectionPrivate *d = _q_manager()->connection(name);
371 if (d || name.isEmpty())
372 return QDBusConnection(d);
373
374 d = new QDBusConnectionPrivate;
375 // setConnection does the error handling for us
376 QDBusErrorInternal error;
377 DBusConnection *c = q_dbus_connection_open_private(address.toUtf8().constData(), error);
378 if (c) {
379 if (!q_dbus_bus_register(c, error)) {
380 q_dbus_connection_unref(c);
381 c = 0;
382 }
383 }
384 d->setConnection(c, error);
385 _q_manager()->setConnection(name, d);
386
387 QDBusConnection retval(d);
388
389 // create the bus service
390 // will lock in QDBusConnectionPrivate::connectRelay()
391 d->setBusService(retval);
392
393 return retval;
394}
395
396/*!
397 Closes the connection of name \a name.
398
399 Note that if there are still QDBusConnection objects associated
400 with the same connection, the connection will not be closed until
401 all references are dropped. However, no further references can be
402 created using the QDBusConnection constructor.
403*/
404void QDBusConnection::disconnectFromBus(const QString &name)
405{
406 if (_q_manager()) {
407 QMutexLocker locker(&_q_manager()->mutex);
408 _q_manager()->removeConnection(name);
409 }
410}
411
412/*!
413 Sends the \a message over this connection, without waiting for a
414 reply. This is suitable for errors, signals, and return values as
415 well as calls whose return values are not necessary.
416
417 Returns true if the message was queued successfully, false otherwise.
418*/
419bool QDBusConnection::send(const QDBusMessage &message) const
420{
421 if (!d || !d->connection) {
422 QDBusError err = QDBusError(QDBusError::Disconnected,
423 QLatin1String("Not connected to D-BUS server"));
424 if (d)
425 d->lastError = err;
426 return false;
427 }
428 return d->send(message) != 0;
429}
430
431/*!
432 Sends the \a message over this connection and returns immediately.
433 When the reply is received, the method \a returnMethod is called in
434 the \a receiver object. If an error occurs, the method \a errorMethod
435 will be called instead.
436
437 If no reply is received within \a timeout milliseconds, an automatic
438 error will be delivered indicating the expiration of the call.
439 The default \a timeout is -1, which will be replaced with an
440 implementation-defined value that is suitable for inter-process
441 communications (generally, 25 seconds).
442
443 This function is suitable for method calls only. It is guaranteed
444 that the slot will be called exactly once with the reply, as long
445 as the parameter types match and no error occurs.
446
447 Returns true if the message was sent, or false if the message could
448 not be sent.
449*/
450bool QDBusConnection::callWithCallback(const QDBusMessage &message, QObject *receiver,
451 const char *returnMethod, const char *errorMethod,
452 int timeout) const
453{
454 if (!d || !d->connection) {
455 QDBusError err = QDBusError(QDBusError::Disconnected,
456 QLatin1String("Not connected to D-BUS server"));
457 if (d)
458 d->lastError = err;
459 return false;
460 }
461 return d->sendWithReplyAsync(message, receiver, returnMethod, errorMethod, timeout) != 0;
462}
463
464/*!
465 \overload
466 \deprecated
467 Sends the \a message over this connection and returns immediately.
468 When the reply is received, the method \a returnMethod is called in
469 the \a receiver object.
470
471 This function is suitable for method calls only. It is guaranteed
472 that the slot will be called exactly once with the reply, as long
473 as the parameter types match and no error occurs.
474
475 This function is dangerous because it cannot report errors, including
476 the expiration of the timeout.
477
478 Returns true if the message was sent, or false if the message could
479 not be sent.
480*/
481bool QDBusConnection::callWithCallback(const QDBusMessage &message, QObject *receiver,
482 const char *returnMethod, int timeout) const
483{
484 return callWithCallback(message, receiver, returnMethod, 0, timeout);
485}
486
487/*!
488 Sends the \a message over this connection and blocks, waiting for
489 a reply, for at most \a timeout milliseconds. This function is
490 suitable for method calls only. It returns the reply message as
491 its return value, which will be either of type
492 QDBusMessage::ReplyMessage or QDBusMessage::ErrorMessage.
493
494 If no reply is received within \a timeout milliseconds, an automatic
495 error will be delivered indicating the expiration of the call.
496 The default \a timeout is -1, which will be replaced with an
497 implementation-defined value that is suitable for inter-process
498 communications (generally, 25 seconds).
499
500 See the QDBusInterface::call() function for a more friendly way
501 of placing calls.
502
503 \warning If \a mode is QDBus::BlockWithGui, this function will
504 reenter the Qt event loop in order to wait for the
505 reply. During the wait, it may deliver signals and other
506 method calls to your application. Therefore, it must be
507 prepared to handle a reentrancy whenever a call is
508 placed with call().
509*/
510QDBusMessage QDBusConnection::call(const QDBusMessage &message, QDBus::CallMode mode, int timeout) const
511{
512 if (!d || !d->connection) {
513 QDBusError err = QDBusError(QDBusError::Disconnected,
514 QLatin1String("Not connected to D-Bus server"));
515 if (d)
516 d->lastError = err;
517
518 return QDBusMessage::createError(err);
519 }
520
521 if (mode != QDBus::NoBlock)
522 return d->sendWithReply(message, mode, timeout);
523
524 d->send(message);
525 QDBusMessage retval;
526 retval << QVariant(); // add one argument (to avoid .at(0) problems)
527 return retval;
528}
529
530/*!
531 \since 4.5
532 Sends the \a message over this connection and returns
533 immediately. This function is suitable for method calls only. It
534 returns an object of type QDBusPendingCall which can be used to
535 track the status of the reply.
536
537 If no reply is received within \a timeout milliseconds, an automatic
538 error will be delivered indicating the expiration of the call. The
539 default \a timeout is -1, which will be replaced with an
540 implementation-defined value that is suitable for inter-process
541 communications (generally, 25 seconds). This timeout is also the
542 upper limit for waiting in QDBusPendingCall::waitForFinished().
543
544 See the QDBusInterface::asyncCall() function for a more friendly way
545 of placing calls.
546*/
547QDBusPendingCall QDBusConnection::asyncCall(const QDBusMessage &message, int timeout) const
548{
549 if (!d || !d->connection) {
550 return QDBusPendingCall(0); // null pointer -> disconnected
551 }
552
553 QDBusPendingCallPrivate *priv = d->sendWithReplyAsync(message, timeout);
554 return QDBusPendingCall(priv);
555}
556
557/*!
558 Connects the signal specified by the \a service, \a path, \a interface and \a name parameters to
559 the slot \a slot in object \a receiver. The arguments \a service and \a path can be empty,
560 denoting a connection to any signal of the (\a interface, \a name) pair, from any remote
561 application.
562
563 Returns true if the connection was successful.
564
565 \warning The signal will only be delivered to the slot if the parameters match. This verification
566 can be done only when the signal is received, not at connection time.
567*/
568bool QDBusConnection::connect(const QString &service, const QString &path, const QString& interface,
569 const QString &name, QObject *receiver, const char *slot)
570{
571 return connect(service, path, interface, name, QStringList(), QString(), receiver, slot);
572}
573
574/*!
575 \overload
576
577 Connects the signal to the slot \a slot in object \a
578 receiver. Unlike the previous connect() overload, this function
579 allows one to specify the parameter signature to be connected
580 using the \a signature variable. The function will then verify
581 that this signature can be delivered to the slot specified by \a
582 slot and return false otherwise.
583
584 Returns true if the connection was successful.
585
586 \note This function verifies that the signal signature matches the
587 slot's parameters, but it does not verify that the actual
588 signal exists with the given signature in the remote
589 service.
590*/
591bool QDBusConnection::connect(const QString &service, const QString &path, const QString& interface,
592 const QString &name, const QString &signature,
593 QObject *receiver, const char *slot)
594{
595 return connect(service, path, interface, name, QStringList(), signature, receiver, slot);
596}
597
598/*!
599 \overload
600 \since 4.6
601
602 Connects the signal to the slot \a slot in object \a
603 receiver. Unlike the previous connect() overload, this function
604 allows one to specify the parameter signature to be connected
605 using the \a signature variable. The function will then verify
606 that this signature can be delivered to the slot specified by \a
607 slot and return false otherwise.
608
609 The \a argumentMatch parameter lists the string parameters to be matched,
610 in sequential order. Note that, to match an empty string, you need to
611 pass a QString that is empty but not null (i.e., QString("")). A null
612 QString skips matching at that position.
613
614 Returns true if the connection was successful.
615
616 \note This function verifies that the signal signature matches the
617 slot's parameters, but it does not verify that the actual
618 signal exists with the given signature in the remote
619 service.
620*/
621bool QDBusConnection::connect(const QString &service, const QString &path, const QString& interface,
622 const QString &name, const QStringList &argumentMatch, const QString &signature,
623 QObject *receiver, const char *slot)
624{
625
626 if (!receiver || !slot || !d || !d->connection)
627 return false;
628 if (!interface.isEmpty() && !QDBusUtil::isValidInterfaceName(interface))
629 return false;
630 if (interface.isEmpty() && name.isEmpty())
631 return false;
632
633 QDBusWriteLocker locker(ConnectAction, d);
634 return d->connectSignal(service, path, interface, name, argumentMatch, signature, receiver, slot);
635}
636
637/*!
638 Disconnects the signal specified by the \a service, \a path, \a interface
639 and \a name parameters from the slot \a slot in object \a receiver. The
640 arguments must be the same as passed to the connect() function.
641
642 Returns true if the disconnection was successful.
643*/
644bool QDBusConnection::disconnect(const QString &service, const QString &path, const QString &interface,
645 const QString &name, QObject *receiver, const char *slot)
646{
647 return disconnect(service, path, interface, name, QStringList(), QString(), receiver, slot);
648}
649
650/*!
651 \overload
652
653 Disconnects the signal specified by the \a service, \a path, \a
654 interface, \a name, and \a signature parameters from the slot \a slot in
655 object \a receiver. The arguments must be the same as passed to the
656 connect() function.
657
658 Returns true if the disconnection was successful.
659*/
660bool QDBusConnection::disconnect(const QString &service, const QString &path, const QString& interface,
661 const QString &name, const QString &signature,
662 QObject *receiver, const char *slot)
663{
664 return disconnect(service, path, interface, name, QStringList(), signature, receiver, slot);
665}
666
667/*!
668 \overload
669 \since 4.6
670
671 Disconnects the signal specified by the \a service, \a path, \a
672 interface, \a name, \a argumentMatch, and \a signature parameters from
673 the slot \a slot in object \a receiver. The arguments must be the same as
674 passed to the connect() function.
675
676 Returns true if the disconnection was successful.
677*/
678bool QDBusConnection::disconnect(const QString &service, const QString &path, const QString& interface,
679 const QString &name, const QStringList &argumentMatch, const QString &signature,
680 QObject *receiver, const char *slot)
681{
682 if (!receiver || !slot || !d || !d->connection)
683 return false;
684 if (!interface.isEmpty() && !QDBusUtil::isValidInterfaceName(interface))
685 return false;
686 if (interface.isEmpty() && name.isEmpty())
687 return false;
688
689 QDBusWriteLocker locker(DisconnectAction, d);
690 return d->disconnectSignal(service, path, interface, name, argumentMatch, signature, receiver, slot);
691}
692
693/*!
694 Registers the object \a object at path \a path and returns true if
695 the registration was successful. The \a options parameter
696 specifies how much of the object \a object will be exposed through
697 D-Bus.
698
699 This function does not replace existing objects: if there is already an object registered at
700 path \a path, this function will return false. Use unregisterObject() to unregister it first.
701
702 You cannot register an object as a child object of an object that
703 was registered with QDBusConnection::ExportChildObjects.
704*/
705bool QDBusConnection::registerObject(const QString &path, QObject *object, RegisterOptions options)
706{
707 Q_ASSERT_X(QDBusUtil::isValidObjectPath(path), "QDBusConnection::registerObject",
708 "Invalid object path given");
709 if (!d || !d->connection || !object || !options || !QDBusUtil::isValidObjectPath(path))
710 return false;
711
712 QStringList pathComponents = path.split(QLatin1Char('/'));
713 if (pathComponents.last().isEmpty())
714 pathComponents.removeLast();
715 QDBusWriteLocker locker(RegisterObjectAction, d);
716
717 // lower-bound search for where this object should enter in the tree
718 QDBusConnectionPrivate::ObjectTreeNode *node = &d->rootNode;
719 int i = 1;
720 while (node) {
721 if (pathComponents.count() == i) {
722 // this node exists
723 // consider it free if there's no object here and the user is not trying to
724 // replace the object sub-tree
725 if ((options & ExportChildObjects && !node->children.isEmpty()) || node->obj)
726 return false;
727
728 // we can add the object here
729 node->obj = object;
730 node->flags = options;
731
732 d->registerObject(node);
733 //qDebug("REGISTERED FOR %s", path.toLocal8Bit().constData());
734 return true;
735 }
736
737 // find the position where we'd insert the node
738 QDBusConnectionPrivate::ObjectTreeNode::DataList::Iterator it =
739 qLowerBound(node->children.begin(), node->children.end(), pathComponents.at(i));
740 if (it != node->children.end() && it->name == pathComponents.at(i)) {
741 // match: this node exists
742 node = it;
743
744 // are we allowed to go deeper?
745 if (node->flags & ExportChildObjects) {
746 // we're not
747 qDebug("Cannot register object at %s because %s exports its own child objects",
748 qPrintable(path), qPrintable(pathComponents.at(i)));
749 return false;
750 }
751 } else {
752 // add entry
753 node = node->children.insert(it, pathComponents.at(i));
754 }
755
756 // iterate
757 ++i;
758 }
759
760 Q_ASSERT_X(false, "QDBusConnection::registerObject", "The impossible happened");
761 return false;
762}
763
764/*!
765 Unregisters an object that was registered with the registerObject() at the object path given by
766 \a path and, if \a mode is QDBusConnection::UnregisterTree, all of its sub-objects too.
767
768 Note that you cannot unregister objects that were not registered with registerObject().
769*/
770void QDBusConnection::unregisterObject(const QString &path, UnregisterMode mode)
771{
772 if (!d || !d->connection || !QDBusUtil::isValidObjectPath(path))
773 return;
774
775 QStringList pathComponents = path.split(QLatin1Char('/'));
776 QDBusWriteLocker locker(UnregisterObjectAction, d);
777 QDBusConnectionPrivate::ObjectTreeNode *node = &d->rootNode;
778 int i = 1;
779
780 // find the object
781 while (node) {
782 if (pathComponents.count() == i) {
783 // found it
784 node->obj = 0;
785 node->flags = 0;
786
787 if (mode == UnregisterTree) {
788 // clear the sub-tree as well
789 node->children.clear(); // can't disconnect the objects because we really don't know if they can
790 // be found somewhere else in the path too
791 }
792
793 return;
794 }
795
796 QDBusConnectionPrivate::ObjectTreeNode::DataList::Iterator it =
797 qLowerBound(node->children.begin(), node->children.end(), pathComponents.at(i));
798 if (it == node->children.end() || it->name != pathComponents.at(i))
799 break; // node not found
800
801 node = it;
802 ++i;
803 }
804}
805
806/*!
807 Return the object that was registered with the registerObject() at the object path given by
808 \a path.
809*/
810QObject *QDBusConnection::objectRegisteredAt(const QString &path) const
811{
812 Q_ASSERT_X(QDBusUtil::isValidObjectPath(path), "QDBusConnection::registeredObject",
813 "Invalid object path given");
814 if (!d || !d->connection || !QDBusUtil::isValidObjectPath(path))
815 return false;
816
817 QStringList pathComponents = path.split(QLatin1Char('/'));
818 if (pathComponents.last().isEmpty())
819 pathComponents.removeLast();
820
821 // lower-bound search for where this object should enter in the tree
822 QDBusReadLocker lock(ObjectRegisteredAtAction, d);
823 const QDBusConnectionPrivate::ObjectTreeNode *node = &d->rootNode;
824
825 int i = 1;
826 while (node) {
827 if (pathComponents.count() == i)
828 return node->obj;
829
830 QDBusConnectionPrivate::ObjectTreeNode::DataList::ConstIterator it =
831 qLowerBound(node->children.constBegin(), node->children.constEnd(), pathComponents.at(i));
832 if (it == node->children.constEnd() || it->name != pathComponents.at(i))
833 break; // node not found
834
835 node = it;
836 ++i;
837 }
838 return 0;
839}
840
841/*!
842 Returns a QDBusConnectionInterface object that represents the
843 D-Bus server interface on this connection.
844*/
845QDBusConnectionInterface *QDBusConnection::interface() const
846{
847 if (!d)
848 return 0;
849 return d->busService;
850}
851
852/*!
853 Returns true if this QDBusConnection object is connected.
854
855 If it isn't connected, calling connectToBus() on the same
856 connection name will not make be connected. You need to call the
857 QDBusConnection constructor again.
858*/
859bool QDBusConnection::isConnected() const
860{
861 return d && d->connection && q_dbus_connection_get_is_connected(d->connection);
862}
863
864/*!
865 Returns the last error that happened in this connection.
866
867 This function is provided for low-level code. If you're using
868 QDBusInterface::call(), error codes are reported by its return
869 value.
870
871 \sa QDBusInterface, QDBusMessage
872*/
873QDBusError QDBusConnection::lastError() const
874{
875 return d ? d->lastError : QDBusError();
876}
877
878/*!
879 Returns the unique connection name for this connection, if this QDBusConnection object is
880 connected, or an empty QString otherwise.
881
882 A Unique Connection Name is a string in the form ":x.xxx" (where x
883 are decimal digits) that is assigned by the D-Bus server daemon
884 upon connection. It uniquely identifies this client in the bus.
885
886 This function returns an empty QString for peer-to-peer connections.
887*/
888QString QDBusConnection::baseService() const
889{
890 return d ? d->baseService : QString();
891}
892
893/*!
894 \since 4.5
895
896 Returns the connection name for this connection, as given as the
897 name parameter to connectToBus().
898
899 The connection name can be used to uniquely identify actual
900 underlying connections to buses. Copies made from a single
901 connection will always implicitly share the underlying connection,
902 and hence will have the same connection name.
903
904 Inversely, two connections having different connection names will
905 always either be connected to different buses, or have a different
906 unique name (as returned by baseService()) on that bus.
907
908 \sa connectToBus(), disconnectFromBus()
909*/
910QString QDBusConnection::name() const
911{
912 return d ? d->name : QString();
913}
914
915/*!
916 Attempts to register the \a serviceName on the D-Bus server and
917 returns true if the registration succeded. The registration will
918 fail if the name is already registered by another application.
919
920 \sa unregisterService(), QDBusConnectionInterface::registerService()
921*/
922bool QDBusConnection::registerService(const QString &serviceName)
923{
924 if (interface() && interface()->registerService(serviceName)) {
925 if (d) d->registerService(serviceName);
926 return true;
927 }
928 return false;
929}
930
931/*!
932 Unregisters the service \a serviceName that was previously
933 registered with registerService() and returns true if it
934 succeeded.
935
936 \sa registerService(), QDBusConnectionInterface::unregisterService()
937*/
938bool QDBusConnection::unregisterService(const QString &serviceName)
939{
940 if (interface()->unregisterService(serviceName)) {
941 if (d) d->unregisterService(serviceName);
942 return true;
943 }
944 return false;
945}
946
947static const char _q_sessionBusName[] = "qt_default_session_bus";
948static const char _q_systemBusName[] = "qt_default_system_bus";
949
950class QDBusDefaultConnection: public QDBusConnection
951{
952 const char *ownName;
953public:
954 inline QDBusDefaultConnection(BusType type, const char *name)
955 : QDBusConnection(connectToBus(type, QString::fromLatin1(name))), ownName(name)
956 { }
957
958 inline ~QDBusDefaultConnection()
959 { disconnectFromBus(QString::fromLatin1(ownName)); }
960};
961
962Q_GLOBAL_STATIC_WITH_ARGS(QDBusDefaultConnection, _q_sessionBus,
963 (QDBusConnection::SessionBus, _q_sessionBusName))
964Q_GLOBAL_STATIC_WITH_ARGS(QDBusDefaultConnection, _q_systemBus,
965 (QDBusConnection::SystemBus, _q_systemBusName))
966
967QDBusConnection QDBusConnection::sessionBus()
968{
969 return *_q_sessionBus();
970}
971
972QDBusConnection QDBusConnection::systemBus()
973{
974 return *_q_systemBus();
975}
976
977/*!
978 \nonreentrant
979
980 Returns the connection that sent the signal, if called in a slot activated
981 by QDBus; otherwise it returns 0.
982
983 \note Please avoid this function. This function is not thread-safe, so if
984 there's any other thread delivering a D-Bus call, this function may return
985 the wrong connection. In new code, please use QDBusContext::connection()
986 (see that class for a description on how to use it).
987*/
988QDBusConnection QDBusConnection::sender()
989{
990 return QDBusConnection(_q_manager()->sender());
991}
992
993/*!
994 \internal
995*/
996void QDBusConnectionPrivate::setSender(const QDBusConnectionPrivate *s)
997{
998 _q_manager()->setSender(s);
999}
1000
1001/*!
1002 \internal
1003*/
1004void QDBusConnectionPrivate::setConnection(const QString &name, QDBusConnectionPrivate *c)
1005{
1006 _q_manager()->setConnection(name, c);
1007}
1008
1009/*!
1010 \internal
1011*/
1012void QDBusConnectionPrivate::setBusService(const QDBusConnection &connection)
1013{
1014 busService = new QDBusConnectionInterface(connection, this);
1015 ref.deref(); // busService has increased the refcounting to us
1016 // avoid cyclic refcounting
1017
1018 QObject::connect(this, SIGNAL(callWithCallbackFailed(QDBusError,QDBusMessage)),
1019 busService, SIGNAL(callWithCallbackFailed(QDBusError,QDBusMessage)),
1020 Qt::QueuedConnection);
1021}
1022
1023/*!
1024 \namespace QDBus
1025 \inmodule QtDBus
1026
1027 \brief The QDBus namespace contains miscellaneous identifiers used
1028 throughout the QtDBus library.
1029*/
1030
1031/*!
1032 \enum QDBus::CallMode
1033
1034 This enum describes the various ways of placing a function call. The valid modes are:
1035
1036 \value NoBlock Place the call but don't wait for the reply (the reply's contents
1037 will be discarded).
1038 \value Block Don't use an event loop to wait for a reply, but instead block on
1039 network operations while waiting. This means the
1040 user-interface may not be updated until the function returns.
1041 \value BlockWithGui Use the Qt event loop to wait for a reply. This means that the
1042 user-interface will stay responsive (processing input events),
1043 but it also means other events may happen, like signal delivery
1044 and other D-Bus method calls.
1045 \value AutoDetect Automatically detect if the called function has a reply.
1046
1047 When using BlockWithGui, applications must be prepared for reentrancy in any function.
1048*/
1049
1050QT_END_NAMESPACE
Note: See TracBrowser for help on using the repository browser.