1 # Copyright (C) 2007 Collabora Ltd. <http://www.collabora.co.uk/>
3 # Licensed under the Academic Free License version 2.1
5 # This program is free software; you can redistribute it and/or modify
6 # it under the terms of the GNU Lesser General Public License as published
7 # by the Free Software Foundation; either version 2.1 of the License, or
8 # (at your option) any later version.
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU General Public License for more details.
15 # You should have received a copy of the GNU General Public License
16 # along with this program; if not, write to the Free Software
17 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 from _dbus_bindings
import validate_interface_name
, validate_member_name
,\
20 validate_bus_name
, validate_object_path
,\
23 BUS_DAEMON_NAME
, BUS_DAEMON_PATH
, BUS_DAEMON_IFACE
24 from dbus
.connection
import Connection
27 class BusConnection(Connection
):
28 """This mixin provides simple blocking wrappers for various methods on
29 the org.freedesktop.DBus bus-daemon object, to reduce the amount of C
33 def activate_name_owner(self
, bus_name
):
34 if (bus_name
is not None and bus_name
[:1] != ':'
35 and bus_name
!= BUS_DAEMON_NAME
):
37 return self
.get_name_owner(bus_name
)
38 except DBusException
, e
:
39 # FIXME: detect whether it's NameHasNoOwner, but properly
40 #if not str(e).startswith('org.freedesktop.DBus.Error.NameHasNoOwner:'):
42 # it might not exist: try to start it
43 self
.start_service_by_name(bus_name
)
44 return self
.get_name_owner(bus_name
)
49 def get_unix_user(self
, bus_name
):
50 """Get the numeric uid of the process owning the given bus name.
54 A bus name, either unique or well-known
55 :Returns: a `dbus.UInt32`
57 validate_bus_name(bus_name
)
58 return self
.call_blocking(BUS_DAEMON_NAME
, BUS_DAEMON_PATH
,
59 BUS_DAEMON_IFACE
, 'GetConnectionUnixUser',
62 def start_service_by_name(self
, bus_name
, flags
=0):
63 """Start a service which will implement the given bus name on this Bus.
67 The well-known bus name to be activated.
69 Flags to pass to StartServiceByName (currently none are
72 :Returns: A tuple of 2 elements. The first is always True, the
73 second is either START_REPLY_SUCCESS or
74 START_REPLY_ALREADY_RUNNING.
76 :Raises DBusException: if the service could not be started.
78 validate_bus_name(bus_name
)
79 return (True, self
.call_blocking(BUS_DAEMON_NAME
, BUS_DAEMON_PATH
,
82 'su', (bus_name
, flags
)))
84 # XXX: it might be nice to signal IN_QUEUE, EXISTS by exception,
85 # but this would not be backwards-compatible
86 def request_name(self
, name
, flags
=0):
87 """Request a bus name.
91 The well-known name to be requested
93 A bitwise-OR of 0 or more of the flags
94 `DBUS_NAME_FLAG_ALLOW_REPLACEMENT`,
95 `DBUS_NAME_FLAG_REPLACE_EXISTING`
96 and `DBUS_NAME_FLAG_DO_NOT_QUEUE`
97 :Returns: `DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER`,
98 `DBUS_REQUEST_NAME_REPLY_IN_QUEUE`,
99 `DBUS_REQUEST_NAME_REPLY_EXISTS` or
100 `DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER`
101 :Raises DBusException: if the bus daemon cannot be contacted or
104 validate_bus_name(name
, allow_unique
=False)
105 return self
.call_blocking(BUS_DAEMON_NAME
, BUS_DAEMON_PATH
,
106 BUS_DAEMON_IFACE
, 'RequestName',
109 def release_name(self
, name
):
110 """Release a bus name.
114 The well-known name to be released
115 :Returns: `DBUS_RELEASE_NAME_REPLY_RELEASED`,
116 `DBUS_RELEASE_NAME_REPLY_NON_EXISTENT`
117 or `DBUS_RELEASE_NAME_REPLY_NOT_OWNER`
118 :Raises DBusException: if the bus daemon cannot be contacted or
121 validate_bus_name(name
, allow_unique
=False)
122 return self
.call_blocking(BUS_DAEMON_NAME
, BUS_DAEMON_PATH
,
123 BUS_DAEMON_IFACE
, 'ReleaseName',
126 def list_names(self
):
127 """Return a list of all currently-owned names on the bus.
129 :Returns: a dbus.Array of dbus.UTF8String
131 return self
.call_blocking(BUS_DAEMON_NAME
, BUS_DAEMON_PATH
,
132 BUS_DAEMON_IFACE
, 'ListNames',
133 '', (), utf8_strings
=True)
135 def list_activatable_names(self
):
136 """Return a list of all names that can be activated on the bus.
138 :Returns: a dbus.Array of dbus.UTF8String
140 return self
.call_blocking(BUS_DAEMON_NAME
, BUS_DAEMON_PATH
,
141 BUS_DAEMON_IFACE
, 'ListNames',
142 '', (), utf8_strings
=True)
144 def get_name_owner(self
, bus_name
):
145 """Return the unique connection name of the primary owner of the
148 :Raises DBusException: if the `bus_name` has no owner
150 validate_bus_name(bus_name
, allow_unique
=False)
151 return self
.call_blocking(BUS_DAEMON_NAME
, BUS_DAEMON_PATH
,
152 BUS_DAEMON_IFACE
, 'GetNameOwner',
153 's', (bus_name
,), utf8_strings
=True)
155 def name_has_owner(self
, bus_name
):
156 """Return True iff the given bus name has an owner on this bus.
160 The bus name to look up
163 return bool(self
.call_blocking(BUS_DAEMON_NAME
, BUS_DAEMON_PATH
,
164 BUS_DAEMON_IFACE
, 'NameHasOwner',
167 def add_match_string(self
, rule
):
168 """Arrange for this application to receive messages on the bus that
169 match the given rule. This version will block.
174 :Raises: `DBusException` on error.
176 self
.call_blocking(BUS_DAEMON_NAME
, BUS_DAEMON_PATH
,
177 BUS_DAEMON_IFACE
, 'AddMatch', 's', (rule
,))
179 # FIXME: add an async success/error handler capability?
180 # (and the same for remove_...)
181 def add_match_string_non_blocking(self
, rule
):
182 """Arrange for this application to receive messages on the bus that
183 match the given rule. This version will not block, but any errors
190 :Raises: `DBusException` on error.
192 self
.call_async(BUS_DAEMON_NAME
, BUS_DAEMON_PATH
,
193 BUS_DAEMON_IFACE
, 'AddMatch', 's', (rule
,),
196 def remove_match_string(self
, rule
):
197 """Arrange for this application to receive messages on the bus that
198 match the given rule. This version will block.
203 :Raises: `DBusException` on error.
205 self
.call_blocking(BUS_DAEMON_NAME
, BUS_DAEMON_PATH
,
206 BUS_DAEMON_IFACE
, 'RemoveMatch', 's', (rule
,))
208 def remove_match_string_non_blocking(self
, rule
):
209 """Arrange for this application to receive messages on the bus that
210 match the given rule. This version will not block, but any errors
217 :Raises: `DBusException` on error.
219 self
.call_async(BUS_DAEMON_NAME
, BUS_DAEMON_PATH
,
220 BUS_DAEMON_IFACE
, 'RemoveMatch', 's', (rule
,),