home *** CD-ROM | disk | FTP | other *** search
- # Source Generated with Decompyle++
- # File: in.pyc (Python 2.6)
-
- '''Backend manager.
-
- This encapsulates all services of the backend and manages all handlers.
- '''
- import logging
- import os
- import os.path as os
- import signal
- import threading
- import sys
- import gobject
- import dbus
- import dbus.service as dbus
- import dbus.mainloop.glib as dbus
- from oslib import OSLib
- import detection
- import xorg_driver
- DBUS_BUS_NAME = 'com.ubuntu.DeviceDriver'
-
- class UnknownHandlerException(dbus.DBusException):
- _dbus_error_name = 'com.ubuntu.DeviceDriver.UnknownHandlerException'
-
-
- class InvalidModeException(dbus.DBusException):
- _dbus_error_name = 'com.ubuntu.DeviceDriver.InvalidModeException'
-
-
- class InvalidDriverDBException(dbus.DBusException):
- _dbus_error_name = 'com.ubuntu.DeviceDriver.InvalidDriverDBException'
-
-
- class PermissionDeniedByPolicy(dbus.DBusException):
- _dbus_error_name = 'com.ubuntu.DeviceDriver.PermissionDeniedByPolicy'
-
-
- class BackendCrashError(SystemError):
- pass
-
-
- def dbus_sync_call_signal_wrapper(dbus_iface, fn, handler_map, *args, **kwargs):
- '''Run a D-BUS method call while receiving signals.
-
- This function is an Ugly Hack\xe2\x84\xa2, since a normal synchronous dbus_iface.fn()
- call does not cause signals to be received until the method returns. Thus
- it calls fn asynchronously and sets up a temporary main loop to receive
- signals and call their handlers; these are assigned in handler_map (signal
- name \xe2\x86\x92 signal handler).
- '''
- global _h_reply_result, _h_exception_exc
- if not hasattr(dbus_iface, 'connect_to_signal'):
- return getattr(dbus_iface, fn)(*args, **kwargs)
-
- def _h_reply(result):
- global _h_reply_result
- _h_reply_result = result
- loop.quit()
-
-
- def _h_error(exception):
- global _h_exception_exc
- _h_exception_exc = exception
- loop.quit()
-
- loop = gobject.MainLoop()
- _h_reply_result = None
- _h_exception_exc = None
- kwargs['reply_handler'] = _h_reply
- kwargs['error_handler'] = _h_error
- kwargs['timeout'] = 86400
- for signame, sighandler in handler_map.iteritems():
- dbus_iface.connect_to_signal(signame, sighandler)
-
- dbus_iface.get_dbus_method(fn)(*args, **kwargs)
- loop.run()
- if _h_exception_exc:
- raise _h_exception_exc
- _h_exception_exc
- return _h_reply_result
-
-
- def polkit_auth_wrapper(fn, *args, **kwargs):
- '''Function call wrapper for PolicyKit authentication.
-
- Call fn(*args, **kwargs). If it fails with a PermissionDeniedByPolicy
- and the caller can authenticate to get the missing privilege, the PolicyKit
- authentication agent is called, and the function call is attempted again.
-
- This function also translates DBusExceptions into the Exceptions defined
- above.
- '''
-
- try:
-
- try:
- return fn(*args, **kwargs)
- except dbus.DBusException:
- e = None
- if e._dbus_error_name == PermissionDeniedByPolicy._dbus_error_name:
- (priv, auth_result) = str(e).split()[-2:]
- if auth_result.startswith('auth_'):
- pk_auth = dbus.Interface(dbus.SessionBus().get_object('org.freedesktop.PolicyKit.AuthenticationAgent', '/', False), 'org.freedesktop.PolicyKit.AuthenticationAgent')
- res = pk_auth.ObtainAuthorization(priv, dbus.UInt32(0), dbus.UInt32(os.getpid()), timeout = 300)
- if res:
- return fn(*args, **kwargs)
-
- raise PermissionDeniedByPolicy(priv + ' ' + auth_result)
- e._dbus_error_name == PermissionDeniedByPolicy._dbus_error_name
- raise
-
- except dbus.DBusException:
- e = None
- if e._dbus_error_name == InvalidModeException._dbus_error_name:
- raise InvalidModeException(str(e))
- e._dbus_error_name == InvalidModeException._dbus_error_name
- if e._dbus_error_name == UnknownHandlerException._dbus_error_name:
- raise UnknownHandlerException(str(e))
- e._dbus_error_name == UnknownHandlerException._dbus_error_name
- if e._dbus_error_name == 'org.freedesktop.DBus.Python.SystemError':
- raise SystemError(str(e))
- e._dbus_error_name == 'org.freedesktop.DBus.Python.SystemError'
- if e._dbus_error_name == 'org.freedesktop.DBus.Error.NoReply':
- raise BackendCrashError
- e._dbus_error_name == 'org.freedesktop.DBus.Error.NoReply'
- raise
-
-
-
- class Backend(dbus.service.Object):
- '''Backend manager.
-
- This encapsulates all services of the backend and manages all handlers. It
- is implemented as a dbus.service.Object, so that it can be called through
- D-BUS as well (on the /DeviceDriver object path).
- '''
- DBUS_INTERFACE_NAME = 'com.ubuntu.DeviceDriver'
-
- def __init__(self, handler_dir = None, detect = True):
- '''Initialize backend (no hardware/driver detection).
-
- In order to be fast and not block client side applications for very
- long, detect can be set to False; in that case this constructor does
- not detect hardware and drivers, and client-side applications must call
- detect() at program start.
- '''
- self.handler_dir = handler_dir
- self.handler_pool = { }
- self.hardware = None
- self.dbus_info = None
- self.polkit = None
- self.enforce_polkit = True
- self._package_operation_in_progress = False
- if detect:
- self.detect()
-
-
-
- def detect(self, sender = None, conn = None):
- '''Detect available hardware and handlers.
-
- This method can take pretty long, so it should be called asynchronously
- with a large (or indefinite) timeout, and client UIs should display a
- bouncing progress bar (if appropriate). If the backend is already
- initialized, this returns immediately.
-
- This must be called once at client-side program start.
- '''
- self._reset_timeout()
- self._check_polkit_privilege(sender, conn, 'com.ubuntu.devicedriver.info')
- if not self.hardware:
- self.hardware = detection.get_hardware()
- self.driver_dbs = [
- detection.LocalKernelModulesDriverDB(),
- detection.OpenPrintingDriverDB()]
- self._detect_handlers()
-
-
- detect = dbus.service.method(DBUS_INTERFACE_NAME, in_signature = '', out_signature = '', sender_keyword = 'sender', connection_keyword = 'conn')(detect)
-
- def available(self, mode = 'any', sender = None, conn = None):
- '''List available driver IDs.
-
- Mode can be "any" (default) to return all available drivers, or
- "free"/"nonfree" to select by license.
- '''
- self._reset_timeout()
- self._check_polkit_privilege(sender, conn, 'com.ubuntu.devicedriver.info')
- if mode == 'any':
- return self.handlers.keys()
- if mode not in ('free', 'nonfree'):
- raise InvalidModeException('invalid mode %s: must be "free", "nonfree", or "any"' % mode)
- mode not in ('free', 'nonfree')
- recommended = []
- nonrecommended = []
- for h_id, h in self.handlers.iteritems():
- if h.free() == mode == 'free':
- if h.recommended():
- recommended.append(h_id)
- else:
- nonrecommended.append(h_id)
- h.recommended()
-
- return recommended + nonrecommended
-
- available = dbus.service.method(DBUS_INTERFACE_NAME, in_signature = 's', out_signature = 'as', sender_keyword = 'sender', connection_keyword = 'conn')(available)
-
- def get_hardware(self, sender = None, conn = None):
- '''List available hardware IDs.'''
- self._reset_timeout()
- self._check_polkit_privilege(sender, conn, 'com.ubuntu.devicedriver.info')
- return [ hwid.type + ':' + hwid.id for hwid in self.hardware ]
-
- get_hardware = dbus.service.method(DBUS_INTERFACE_NAME, in_signature = '', out_signature = 'as', sender_keyword = 'sender', connection_keyword = 'conn')(get_hardware)
-
- def handler_info(self, handler_id, sender = None, conn = None):
- """Return details about a particular handler.
-
- The information is returned in a property_name \xe2\x86\x92 property_value
- dictionary. Boolean values are encoded as 'True' and 'False' strings.
- If a particular attribute is not set, it will not appear in the
- dictionary.
- """
- self._reset_timeout()
- self._check_polkit_privilege(sender, conn, 'com.ubuntu.devicedriver.info')
-
- try:
- h = self.handlers[handler_id]
- except KeyError:
- raise UnknownHandlerException('Unknown handler: %s' % handler_id)
-
- info = {
- 'id': h.id(),
- 'name': h.name(),
- 'free': str(h.free()),
- 'enabled': str(h.enabled()),
- 'used': str(h.used()),
- 'changed': str(h.changed()),
- 'recommended': str(h.recommended()),
- 'announce': str(h.announce) }
- for f in [
- 'description',
- 'rationale',
- 'can_change']:
- v = getattr(h, f)()
- if v:
- info[f] = v
- continue
-
- for f in [
- 'package',
- 'repository',
- 'driver_vendor',
- 'version',
- 'license']:
- v = getattr(h, f)
- if v:
- info[f] = v
- continue
-
- return info
-
- handler_info = dbus.service.method(DBUS_INTERFACE_NAME, in_signature = 's', out_signature = 'a{ss}', sender_keyword = 'sender', connection_keyword = 'conn')(handler_info)
-
- def handler_files(self, handler_id, sender = None, conn = None):
- '''Return list of files installed by a handler.'''
-
- try:
- h = self.handlers[handler_id]
- except KeyError:
- raise UnknownHandlerException('Unknown handler: %s' % handler_id)
-
- if not (h.package) or not h.enabled():
- return []
-
- try:
- return OSLib.inst.package_files(h.package)
- except ValueError:
- not h.enabled()
- not h.enabled()
- return []
-
-
- handler_files = dbus.service.method(DBUS_INTERFACE_NAME, in_signature = 's', out_signature = 'as', sender_keyword = 'sender', connection_keyword = 'conn')(handler_files)
-
- def set_enabled(self, handler_id, enable, sender = None, conn = None):
- '''Enable or disable a driver.
-
- This enables (enable=True) or disables (enable=False) the given Driver
- ID. Return True if the handler could be activated immediately, or False
- if the system needs a reboot for the changes to become effective.
- '''
- self._reset_timeout()
- self._check_polkit_privilege(sender, conn, 'com.ubuntu.devicedriver.install')
-
- try:
- h = self.handlers[handler_id]
- except KeyError:
- raise UnknownHandlerException('Unknown handler: %s' % handler_id)
-
- if enable:
- f = h.enable
- else:
- f = h.disable
- if not conn:
- return f()
- if h.package:
- if enable:
- self.install_progress('download', -1, -1)
- else:
- self.remove_progress(-1, -1)
-
-
- def _f_result_wrapper():
-
- try:
- self._f_result = f()
- except:
- self._f_exception = sys.exc_info()
-
-
- self._f_exception = None
- t_f = threading.Thread(None, _f_result_wrapper, 'thread_enable_disable', [], { })
- t_f.start()
- while True:
- t_f.join(0.2)
- if not t_f.isAlive():
- break
-
- if not self._package_operation_in_progress:
- if enable:
- self.install_progress('install', -1, -1)
- else:
- self.remove_progress(-1, -1)
- enable
- if self._f_exception:
- raise self._f_exception[0], self._f_exception[1], self._f_exception[2]
- self._f_exception
- return self._f_result
-
- set_enabled = dbus.service.method(DBUS_INTERFACE_NAME, in_signature = 'sb', out_signature = 'b', sender_keyword = 'sender', connection_keyword = 'conn')(set_enabled)
-
- def new_used_available(self, mode = 'any', sender = None, conn = None):
- '''Check for newly used or available drivers since last call.
-
- Return (new_used, new_avail) with lists of new drivers which are in
- use, and new drivers which got available but are disabled.
- Mode can be "any" (default) to return all available drivers, or
- "free"/"nonfree" to select by license.
- '''
- self._reset_timeout()
- self._check_polkit_privilege(sender, conn, 'com.ubuntu.devicedriver.check')
- if mode not in ('any', 'free', 'nonfree'):
- raise InvalidModeException('invalid mode %s: must be "free", "nonfree", or "any"' % mode)
- mode not in ('any', 'free', 'nonfree')
- seen = set()
- used = set()
- if os.path.exists(OSLib.inst.check_cache):
- f = open(OSLib.inst.check_cache)
- for line in f:
-
- try:
- (flag, h) = line.split(None, 1)
- h = unicode(h, 'UTF-8')
- except ValueError:
- logging.error('invalid line in %s: %s', OSLib.inst.check_cache, line)
-
- if flag == 'seen':
- seen.add(h.strip())
- continue
- if flag == 'used':
- used.add(h.strip())
- continue
- logging.error('invalid flag in %s: %s', OSLib.inst.check_cache, line)
-
- f.close()
-
- new_avail = []
- new_used = []
- for h_id, h in self.handlers.iteritems():
- if (mode == 'free' or not h.free() or mode == 'nonfree') and h.free():
- continue
-
- if h_id not in seen:
- new_avail.append(h_id)
- logging.debug('handler %s previously unseen', h_id)
-
- if h_id not in used and h.used():
- new_used.append(h_id)
- logging.debug('handler %s previously unused', h_id)
- continue
-
- logging.debug('writing back check cache %s', OSLib.inst.check_cache)
- seen.update(new_avail)
- used.update(new_used)
- f = open(OSLib.inst.check_cache, 'w')
- for s in seen:
- print >>f, 'seen', s
-
- for u in used:
- print >>f, 'used', u
-
- f.close()
- for h_id in new_avail + []:
-
- try:
- if self.handlers[h_id].enabled():
- logging.debug('%s is already enabled or not available, not announcing', h_id)
- new_avail.remove(h_id)
- continue
- except ValueError:
- continue
- continue
-
-
-
- return (new_used, new_avail)
-
- new_used_available = dbus.service.method(DBUS_INTERFACE_NAME, in_signature = 's', out_signature = '(asas)', sender_keyword = 'sender', connection_keyword = 'conn')(new_used_available)
-
- def check_composite(self, sender = None, conn = None):
- '''Check for a composite-enabling X.org driver.
-
- If one is available and not enabled, return its ID, otherwise return
- an empty string.
- '''
- self._reset_timeout()
- self._check_polkit_privilege(sender, conn, 'com.ubuntu.devicedriver.info')
- for h_id, h in self.handlers.iteritems():
- if isinstance(h, xorg_driver.XorgDriverHandler) and h.enables_composite():
- if h.enabled():
- logging.debug('Driver "%s" is already enabled and supports the composite extension.' % h.name())
- return ''
- return h_id
- h.enables_composite()
-
- return ''
-
- check_composite = dbus.service.method(DBUS_INTERFACE_NAME, in_signature = '', out_signature = 's', sender_keyword = 'sender', connection_keyword = 'conn')(check_composite)
-
- def add_driverdb(self, db_class, db_args, sender = None, conn = None):
- '''Add driver DB.
-
- db_class is a DriverDB class name; db_args are its constructor
- arguments. If there is an error instantiating the driver DB, an
- InvalidDriverDBException is thrown.
- '''
-
- try:
- cls = getattr(detection, db_class)
- except AttributeError:
- e = None
- raise InvalidDriverDBException(str(e))
-
-
- try:
- inst = cls(*db_args)
- except Exception:
- e = None
- raise InvalidDriverDBException(str(e))
-
- logging.debug('add_driverdb: Adding %s', str(inst))
- self.driver_dbs.append(inst)
- for h in detection.get_db_handlers(self, inst, self.hardware):
- self.handlers[h.id()] = h
-
-
- add_driverdb = dbus.service.method(DBUS_INTERFACE_NAME, in_signature = 'sas', out_signature = '', sender_keyword = 'sender', connection_keyword = 'conn')(add_driverdb)
-
- def update_driverdb(self, sender = None, conn = None):
- '''Query driver DBs for updates.'''
- self._reset_timeout()
- self._check_polkit_privilege(sender, conn, 'com.ubuntu.devicedriver.update')
- for db in self.driver_dbs:
- logging.debug('update_driverdb: updating %s', db.__class__)
- db.update(self.hardware)
-
- self._detect_handlers()
-
- update_driverdb = dbus.service.method(DBUS_INTERFACE_NAME, in_signature = '', out_signature = '', sender_keyword = 'sender', connection_keyword = 'conn')(update_driverdb)
-
- def search_driver(self, hwid, sender = None, conn = None):
- '''Search drivers matching a HardwareID.
-
- This also finds drivers for hardware which is not present locally and
- thus checks all the driver DBs again.
-
- Mode can be "any" (default) to return all available drivers, or
- "free"/"nonfree" to select by license.
- '''
- self._reset_timeout()
- self._check_polkit_privilege(sender, conn, 'com.ubuntu.devicedriver.info')
- (t, i) = hwid.split(':', 1)
- hardware_id = detection.HardwareID(t, i)
- recommended = []
- nonrecommended = []
- for db in self.driver_dbs:
- db.update([
- hardware_id])
-
- handlers = detection.get_handlers(self, self.driver_dbs, hardware = [
- hardware_id], hardware_only = True)
- for h in handlers:
- id = h.id()
- if id not in self.handlers:
- self.handlers[id] = h
-
- if h.recommended():
- recommended.append(id)
- continue
- nonrecommended.append(id)
-
- return recommended + nonrecommended
-
- search_driver = dbus.service.method(DBUS_INTERFACE_NAME, in_signature = 's', out_signature = 'as', sender_keyword = 'sender', connection_keyword = 'conn')(search_driver)
-
- def install_progress(self, phase, curr, total):
- """Report package installation progress.
-
- 'phase' is 'download' or 'install'. current and/or total might be -1 if
- time cannot be determined.
- """
- return False
-
- install_progress = dbus.service.signal(DBUS_INTERFACE_NAME)(install_progress)
-
- def remove_progress(self, curr, total):
- '''Report package removal progress.
-
- current and/or total might be -1 if time cannot be determined.
- '''
- return False
-
- remove_progress = dbus.service.signal(DBUS_INTERFACE_NAME)(remove_progress)
-
- def install_package(self, package):
- '''Install software package.'''
- if OSLib.inst.package_installed(package):
- return None
- self._package_operation_in_progress = True
- if not hasattr(self, '_locations') or self.install_progress:
- pass
- OSLib.inst.install_package(package, None)
- if OSLib.inst.package_installed(package):
- self._update_installed_packages([
- package], [])
-
- self._package_operation_in_progress = False
-
-
- def remove_package(self, package):
- '''Remove software package.'''
- if not OSLib.inst.package_installed(package):
- return None
- self._package_operation_in_progress = True
- if not hasattr(self, '_locations') or self.remove_progress:
- pass
- OSLib.inst.remove_package(package, None)
- if not OSLib.inst.package_installed(package):
- self._update_installed_packages([], [
- package])
-
- self._package_operation_in_progress = False
-
-
- def run_dbus_service(self, timeout = None, send_usr1 = False):
- '''Run D-BUS server.
-
- If no timeout is given, the server will run forever, otherwise it will
- return after the specified number of seconds.
-
- If send_usr1 is True, this will send a SIGUSR1 to the parent process
- once the server is ready to take requests.
- '''
- dbus.service.Object.__init__(self, self.bus, '/DeviceDriver')
- main_loop = gobject.MainLoop()
- self._timeout = False
- if timeout:
-
- def _t():
- main_loop.quit()
- return True
-
- gobject.timeout_add(timeout * 1000, _t)
-
- if send_usr1:
- os.kill(os.getppid(), signal.SIGUSR1)
-
- while not self._timeout:
- if timeout:
- self._timeout = True
-
- main_loop.run()
-
-
- def create_dbus_server(klass, session_bus = False, handler_dir = None):
- '''Return a D-BUS server backend instance.
-
- Normally this connects to the system bus. Set session_bus to True to
- connect to the session bus (for testing).
-
- The created backend does not yet have hardware and drivers detected,
- thus clients need to call detect().
- '''
- import dbus.mainloop.glib as dbus
- backend = Backend(handler_dir, detect = False)
- dbus.mainloop.glib.DBusGMainLoop(set_as_default = True)
- if session_bus:
- backend.bus = dbus.SessionBus()
- backend.enforce_polkit = False
- else:
- backend.bus = dbus.SystemBus()
- backend.dbus_name = dbus.service.BusName(DBUS_BUS_NAME, backend.bus)
- return backend
-
- create_dbus_server = classmethod(create_dbus_server)
-
- def create_dbus_client(klass, session_bus = False):
- '''Return a client-side D-BUS interface for Backend.
-
- Normally this connects to the system bus. Set session_bus to True to
- connect to the session bus (for testing).
- '''
- dbus.mainloop.glib.DBusGMainLoop(set_as_default = True)
- if session_bus:
- bus = dbus.SessionBus()
- else:
- bus = dbus.SystemBus()
- obj = bus.get_object(DBUS_BUS_NAME, '/DeviceDriver')
- return dbus.Interface(obj, Backend.DBUS_INTERFACE_NAME)
-
- create_dbus_client = classmethod(create_dbus_client)
-
- def _update_installed_packages(self, add, remove):
- '''Update backup_dir/installed_packages list of driver packages.
-
- This keeps a log of all packages that jockey installed for supporting
- drivers, so that distribution installers on live CDs can push them into
- the installed system as well.
-
- add and remove are lists which package names to add/remove from it.
- '''
- current = set()
- path = os.path.join(OSLib.inst.backup_dir, 'installed_packages')
- if os.path.exists(path):
- for line in open(path):
- line = line.strip()
- if line:
- current.add(line)
- continue
-
-
- current = current.union(add).difference(remove)
- if current:
- f = open(path, 'w')
- for p in current:
- print >>f, p
-
- f.close()
- elif os.path.exists(path):
- os.unlink(path)
-
-
-
- def _detect_handlers(self):
- '''Detect available handlers and their state.
-
- This initializes self.handlers as id \xe2\x86\x92 Handler map.'''
- self.handlers = { }
- for h in detection.get_handlers(self, self.driver_dbs, handler_dir = self.handler_dir, hardware = self.hardware):
- self.handlers[h.id()] = h
-
-
-
- def _reset_timeout(self):
- '''Reset the D-BUS server timeout.'''
- self._timeout = False
-
-
- def _check_polkit_privilege(self, sender, conn, privilege):
- '''Verify that sender has a given PolicyKit privilege.
-
- sender is the sender\'s (private) D-BUS name, such as ":1:42"
- (sender_keyword in @dbus.service.methods). conn is
- the dbus.Connection object (connection_keyword in
- @dbus.service.methods). privilege is the PolicyKit privilege string.
-
- This method returns if the caller is privileged, and otherwise throws a
- PermissionDeniedByPolicy exception.
- '''
- if sender is None and conn is None:
- return None
- if not self.enforce_polkit:
- return None
- pid = self.dbus_info.GetConnectionUnixProcessID(sender)
- if self.polkit is None:
- self.polkit = dbus.Interface(dbus.SystemBus().get_object('org.freedesktop.PolicyKit', '/', False), 'org.freedesktop.PolicyKit')
-
-
- try:
- res = self.polkit.IsProcessAuthorized(privilege, pid, True)
- except dbus.DBusException:
- e = None
- if e._dbus_error_name == 'org.freedesktop.DBus.Error.ServiceUnknown':
- self.polkit = None
- return self._check_polkit_privilege(sender, conn, privilege)
- raise
- except:
- e._dbus_error_name == 'org.freedesktop.DBus.Error.ServiceUnknown'
-
- if res != 'yes':
- logging.debug('_check_polkit_privilege: sender %s on connection %s pid %i requested %s: %s' % (sender, conn, pid, privilege, res))
- raise PermissionDeniedByPolicy(privilege + ' ' + res)
- res != 'yes'
-
-
-