diff options
Diffstat (limited to 'src/sugar/activity/activity.py')
-rw-r--r-- | src/sugar/activity/activity.py | 138 |
1 files changed, 112 insertions, 26 deletions
diff --git a/src/sugar/activity/activity.py b/src/sugar/activity/activity.py index 7c797e4..c534d75 100644 --- a/src/sugar/activity/activity.py +++ b/src/sugar/activity/activity.py @@ -52,15 +52,25 @@ import logging import os import time from hashlib import sha1 -import gconf +from functools import partial +import gconf import gtk import gobject import dbus import dbus.service +from dbus import PROPERTIES_IFACE import cjson +from telepathy.server import DBusProperties +from telepathy.interfaces import CONNECTION, \ + CHANNEL, \ + CHANNEL_TYPE_TEXT, \ + CLIENT, \ + CLIENT_HANDLER +from telepathy.constants import CONNECTION_HANDLE_TYPE_CONTACT from sugar import util +from sugar import dispatch from sugar.presence import presenceservice from sugar.activity.activityservice import ActivityService from sugar.activity.namingalert import NamingAlert @@ -88,6 +98,7 @@ J_DBUS_SERVICE = 'org.laptop.Journal' J_DBUS_PATH = '/org/laptop/Journal' J_DBUS_INTERFACE = 'org.laptop.Journal' +CONN_INTERFACE_ACTIVITY_PROPERTIES = 'org.laptop.Telepathy.ActivityProperties' class _ActivitySession(gobject.GObject): @@ -300,10 +311,50 @@ class Activity(Window, gtk.Container): if self._jobject.metadata.has_key('share-scope'): share_scope = self._jobject.metadata['share-scope'] + self.shared_activity = None + self._join_id = None + + if handle.handle_invite: + wait_loop = gobject.MainLoop() + self._client_handler = _ClientHandler( + self.get_bundle_id(), + partial(self.__got_channel_cb, wait_loop)) + # The current API requires that self.shared_activity is set before + # exiting from __init__, so we wait until we have got the shared + # activity. + wait_loop.run() + else: + pservice = presenceservice.get_instance() + mesh_instance = pservice.get_activity(self._activity_id, + warn_if_none=False) + self._set_up_sharing(mesh_instance, share_scope) + + if handle.object_id is None and create_jobject: + logging.debug('Creating a jobject.') + self._jobject = datastore.create() + title = _('%s Activity') % get_bundle_name() + self._jobject.metadata['title'] = title + self.set_title(self._jobject.metadata['title']) + self._jobject.metadata['title_set_by_user'] = '0' + self._jobject.metadata['activity'] = self.get_bundle_id() + self._jobject.metadata['activity_id'] = self.get_id() + self._jobject.metadata['keep'] = '0' + self._jobject.metadata['preview'] = '' + self._jobject.metadata['share-scope'] = SCOPE_PRIVATE + if self.shared_activity is not None: + icon_color = self.shared_activity.props.color + else: + client = gconf.client_get_default() + icon_color = client.get_string('/desktop/sugar/user/color') + self._jobject.metadata['icon-color'] = icon_color + + self._jobject.file_path = '' + # Cannot call datastore.write async for creates: + # https://dev.laptop.org/ticket/3071 + datastore.write(self._jobject) + + def _set_up_sharing(self, mesh_instance, share_scope): # handle activity share/join - pservice = presenceservice.get_instance() - mesh_instance = pservice.get_activity(self._activity_id, - warn_if_none=False) logging.debug("*** Act %s, mesh instance %r, scope %s", self._activity_id, mesh_instance, share_scope) if mesh_instance is not None: @@ -331,29 +382,19 @@ class Activity(Window, gtk.Container): else: logging.debug('Unknown share scope %r', share_scope) - if handle.object_id is None and create_jobject: - logging.debug('Creating a jobject.') - self._jobject = datastore.create() - title = _('%s Activity') % get_bundle_name() - self._jobject.metadata['title'] = title - self.set_title(self._jobject.metadata['title']) - self._jobject.metadata['title_set_by_user'] = '0' - self._jobject.metadata['activity'] = self.get_bundle_id() - self._jobject.metadata['activity_id'] = self.get_id() - self._jobject.metadata['keep'] = '0' - self._jobject.metadata['preview'] = '' - self._jobject.metadata['share-scope'] = SCOPE_PRIVATE - if self.shared_activity is not None: - icon_color = self.shared_activity.props.color - else: - client = gconf.client_get_default() - icon_color = client.get_string('/desktop/sugar/user/color') - self._jobject.metadata['icon-color'] = icon_color + def __got_channel_cb(self, wait_loop, connection_path, channel_path): + logging.debug('Activity.__got_channel_cb') + connection_name = connection_path.replace('/', '.')[1:] - self._jobject.file_path = '' - # Cannot call datastore.write async for creates: - # https://dev.laptop.org/ticket/3071 - datastore.write(self._jobject) + bus = dbus.SessionBus() + channel = bus.get_object(connection_name, channel_path) + room_handle = channel.Get(CHANNEL, 'TargetHandle') + + pservice = presenceservice.get_instance() + mesh_instance = pservice.get_activity_by_handle(connection_path, + room_handle) + self._set_up_sharing(mesh_instance, SCOPE_PRIVATE) + wait_loop.quit() def get_active(self): return self._active @@ -646,6 +687,7 @@ class Activity(Window, gtk.Container): def __joined_cb(self, activity, success, err): """Callback when join has finished""" + logging.debug('Activity.__joined_cb %r', success) self.shared_activity.disconnect(self._join_id) self._join_id = None if not success: @@ -854,6 +896,50 @@ class Activity(Window, gtk.Container): # DEPRECATED _shared_activity = property(lambda self: self.shared_activity, None) +SUGAR_CLIENT_PATH = '/org/freedesktop/Telepathy/Client/Sugar' + +class _ClientHandler(dbus.service.Object, DBusProperties): + def __init__(self, bundle_id, got_channel_cb): + self._interfaces = set([CLIENT, CLIENT_HANDLER, PROPERTIES_IFACE]) + self._got_channel_cb = got_channel_cb + + bus = dbus.Bus() + name = CLIENT + '.' + bundle_id + bus_name = dbus.service.BusName(name, bus=bus) + + path = '/' + name.replace('.', '/') + dbus.service.Object.__init__(self, bus_name, path) + DBusProperties.__init__(self) + + self._implement_property_get(CLIENT, { + 'Interfaces': lambda: list(self._interfaces), + }) + self._implement_property_get(CLIENT_HANDLER, { + 'HandlerChannelFilter': self.__get_filters_cb, + }) + + def __get_filters_cb(self): + logging.debug('__get_filters_cb') + filters = { + CHANNEL + '.ChannelType' : CHANNEL_TYPE_TEXT, + CHANNEL + '.TargetHandleType': CONNECTION_HANDLE_TYPE_CONTACT, + } + filter_dict = dbus.Dictionary(filters, signature='sv') + logging.debug('__get_filters_cb %r', dbus.Array([filter_dict], signature='a{sv}')) + return dbus.Array([filter_dict], signature='a{sv}') + + @dbus.service.method(dbus_interface=CLIENT_HANDLER, + in_signature='ooa(oa{sv})aota{sv}', out_signature='') + def HandleChannels(self, account, connection, channels, requests_satisfied, + user_action_time, handler_info): + logging.debug('HandleChannels\n\t%r\n\t%r\n\t%r\n\t%r\n\t%r\n\t%r', + account, connection, channels, requests_satisfied, + user_action_time, handler_info) + try: + for channel in channels: + self._got_channel_cb(connection, channel[0]) + except Exception, e: + logging.exception(e) _session = None |