[Sugar-devel] [PATCH sugar] Fix invitations from a non sugar client (empathy), part of OLPC #10814

Simon Schampijer simon at schampijer.de
Thu Apr 14 13:42:35 EDT 2011


This does bring back the 'invitation from a non-sugar client'
functionality based on the 0.84 code. I did remove the part
where we claim to handle as well video invitations for now,
as we can not handle them.

Signed-off-by: Simon Schampijer <simon at laptop.org>
---
 src/jarabe/model/invites.py         |  133 ++++++++++++++++++++++++-----------
 src/jarabe/model/telepathyclient.py |   11 +++-
 2 files changed, 100 insertions(+), 44 deletions(-)

diff --git a/src/jarabe/model/invites.py b/src/jarabe/model/invites.py
index d2a2e0c..66aabcc 100644
--- a/src/jarabe/model/invites.py
+++ b/src/jarabe/model/invites.py
@@ -17,16 +17,15 @@
 
 import logging
 from functools import partial
+import simplejson
 
 import gobject
 import dbus
+import gconf
 from telepathy.interfaces import CHANNEL, \
                                  CHANNEL_DISPATCHER, \
                                  CHANNEL_DISPATCH_OPERATION, \
                                  CHANNEL_TYPE_CONTACT_LIST, \
-                                 CHANNEL_TYPE_DBUS_TUBE, \
-                                 CHANNEL_TYPE_STREAMED_MEDIA, \
-                                 CHANNEL_TYPE_STREAM_TUBE, \
                                  CHANNEL_TYPE_TEXT, \
                                  CLIENT
 from telepathy.constants import HANDLE_TYPE_ROOM
@@ -45,25 +44,51 @@ CONNECTION_INTERFACE_ACTIVITY_PROPERTIES = \
 _instance = None
 
 
-class ActivityInvite(object):
-    """Invitation to a shared activity."""
-    def __init__(self, dispatch_operation_path, handle, handler,
-                 activity_properties):
+class BaseInvite(object):
+    """Invitation to shared activity or private 1-1 Telepathy channel"""
+    def __init__(self, dispatch_operation_path, handle, handler):
         self.dispatch_operation_path = dispatch_operation_path
         self._handle = handle
         self._handler = handler
 
-        if activity_properties is not None:
-            self._activity_properties = activity_properties
-        else:
-            self._activity_properties = {}
-
     def get_bundle_id(self):
         if CLIENT in self._handler:
             return self._handler[len(CLIENT + '.'):]
         else:
             return None
 
+    def _name_owner_changed_cb(self, name, old_owner, new_owner):
+        logging.debug('BasicInvite._name_owner_changed_cb %r %r %r', name,
+                      new_owner, old_owner)
+        if name == self._handler and new_owner and not old_owner:
+            self._call_handle_with()
+
+    def _call_handle_with(self):
+        bus = dbus.Bus()
+        obj = bus.get_object(CHANNEL_DISPATCHER, self.dispatch_operation_path)
+        dispatch_operation = dbus.Interface(obj, CHANNEL_DISPATCH_OPERATION)
+        dispatch_operation.HandleWith(self._handler,
+            reply_handler=self._handle_with_reply_cb,
+            error_handler=self._handle_with_reply_cb)
+
+    def _handle_with_reply_cb(self, error=None):
+        if error is not None:
+            raise error
+        else:
+            logging.debug('_handle_with_reply_cb')
+
+
+class ActivityInvite(BaseInvite):
+    """Invitation to a shared activity."""
+    def __init__(self, dispatch_operation_path, handle, handler,
+                 activity_properties):
+        BaseInvite.__init__(self, dispatch_operation_path, handle, handler)
+
+        if activity_properties is not None:
+            self._activity_properties = activity_properties
+        else:
+            self._activity_properties = {}
+
     def get_color(self):
         color = self._activity_properties.get('color', None)
         return XoColor(color)
@@ -78,7 +103,7 @@ class ActivityInvite(object):
             self._call_handle_with()
         else:
             bus = dbus.SessionBus()
-            bus.add_signal_receiver(self.__name_owner_changed_cb,
+            bus.add_signal_receiver(self._name_owner_changed_cb,
                                     'NameOwnerChanged',
                                     'org.freedesktop.DBus',
                                     arg0=self._handler)
@@ -88,25 +113,34 @@ class ActivityInvite(object):
             misc.launch(bundle, color=self.get_color(), invited=True,
                         activity_id=activity_id)
 
-    def __name_owner_changed_cb(self, name, old_owner, new_owner):
-        logging.debug('ActivityInvite.__name_owner_changed_cb %r %r %r', name,
-                      new_owner, old_owner)
-        if name == self._handler and new_owner and not old_owner:
-            self._call_handle_with()
 
-    def _call_handle_with(self):
-        bus = dbus.Bus()
-        obj = bus.get_object(CHANNEL_DISPATCHER, self.dispatch_operation_path)
-        dispatch_operation = dbus.Interface(obj, CHANNEL_DISPATCH_OPERATION)
-        dispatch_operation.HandleWith(self._handler,
-            reply_handler=self.__handle_with_reply_cb,
-            error_handler=self.__handle_with_reply_cb)
+class PrivateInvite(BaseInvite):
+    def __init__(self, dispatch_operation_path, handle, handler,
+                 private_channel):
+        BaseInvite.__init__(self, dispatch_operation_path, handle, handler)
 
-    def __handle_with_reply_cb(self, error=None):
-        if error is not None:
-            raise error
+        self._private_channel = private_channel
+
+    def get_color(self):
+        client = gconf.client_get_default()
+        return XoColor(client.get_string('/desktop/sugar/user/color'))
+
+    def join(self):
+        logging.error('PrivateInvite.join handler %r', self._handler)
+
+        registry = bundleregistry.get_registry()
+        bundle_id = self.get_bundle_id()
+        bundle = registry.get_bundle(bundle_id)
+        if bundle is None:
+            self._call_handle_with()
         else:
-            logging.debug('__handle_with_reply_cb')
+            bus = dbus.SessionBus()
+            bus.add_signal_receiver(self._name_owner_changed_cb,
+                                    'NameOwnerChanged',
+                                    'org.freedesktop.DBus',
+                                    arg0=self._handler)
+            misc.launch(bundle, color=self.get_color(), invited=True,
+                        uri=self._private_channel)
 
 
 class Invites(gobject.GObject):
@@ -153,11 +187,15 @@ class Invites(gobject.GObject):
                     error_handler=partial(self.__error_handler_cb,
                                           handle,
                                           channel_properties,
-                                          dispatch_operation_path))
+                                          dispatch_operation_path,
+                                          channel_path,
+                                          properties))
         else:
-            self._dispatch_non_sugar_invitation(channel_path,
+            self._dispatch_non_sugar_invitation(handle,
                                                 channel_properties,
-                                                dispatch_operation_path)
+                                                dispatch_operation_path,
+                                                channel_path,
+                                                properties)
 
     def __get_properties_cb(self, handle, dispatch_operation_path, properties):
         logging.debug('__get_properties_cb %r', properties)
@@ -165,31 +203,30 @@ class Invites(gobject.GObject):
         self._add_invite(dispatch_operation_path, handle, handler, properties)
 
     def __error_handler_cb(self, handle, channel_properties,
-                           dispatch_operation_path, error):
+                           dispatch_operation_path, channel_path,
+                           properties, error):
         logging.debug('__error_handler_cb %r', error)
         exception_name = 'org.freedesktop.Telepathy.Error.NotAvailable'
         if error.get_dbus_name() == exception_name:
             self._dispatch_non_sugar_invitation(handle,
                                                 channel_properties,
-                                                dispatch_operation_path)
+                                                dispatch_operation_path,
+                                                channel_path,
+                                                properties)
         else:
             raise error
 
     def _dispatch_non_sugar_invitation(self, handle, channel_properties,
-                                       dispatch_operation_path):
+                                       dispatch_operation_path, channel_path,
+                                       properties):
         handler = None
         channel_type = channel_properties[CHANNEL + '.ChannelType']
         if channel_type == CHANNEL_TYPE_CONTACT_LIST:
             self._handle_with(dispatch_operation_path, CLIENT + '.Sugar')
         elif channel_type == CHANNEL_TYPE_TEXT:
             handler = CLIENT + '.org.laptop.Chat'
-        elif channel_type == CHANNEL_TYPE_STREAMED_MEDIA:
-            handler = CLIENT + '.org.laptop.VideoChat'
-        elif channel_type == CHANNEL_TYPE_DBUS_TUBE:
-            handler = channel_properties[CHANNEL_TYPE_DBUS_TUBE +
-                                         '.ServiceName']
-        elif channel_type == CHANNEL_TYPE_STREAM_TUBE:
-            handler = channel_properties[CHANNEL_TYPE_STREAM_TUBE + '.Service']
+            self._add_private_invite(dispatch_operation_path, handle, handler,
+                                     channel_path, properties)
         else:
             self._handle_with(dispatch_operation_path, '')
 
@@ -226,6 +263,18 @@ class Invites(gobject.GObject):
         self._dispatch_operations[dispatch_operation_path] = invite
         self.emit('invite-added', invite)
 
+    def _add_private_invite(self, dispatch_operation_path, handle, handler,
+                            channel_path, properties):
+        connection_path = properties[CHANNEL_DISPATCH_OPERATION +
+                                     '.Connection']
+        connection_name = connection_path.replace('/', '.')[1:]
+        private_channel = simplejson.dumps([connection_name,
+                                            connection_path, channel_path])
+        invite = PrivateInvite(dispatch_operation_path, handle, handler,
+                               private_channel)
+        self._dispatch_operations[dispatch_operation_path] = invite
+        self.emit('invite-added', invite)
+
     def remove_invite(self, invite):
         del self._dispatch_operations[invite.dispatch_operation_path]
         self.emit('invite-removed', invite)
diff --git a/src/jarabe/model/telepathyclient.py b/src/jarabe/model/telepathyclient.py
index cea8693..bbd159a 100644
--- a/src/jarabe/model/telepathyclient.py
+++ b/src/jarabe/model/telepathyclient.py
@@ -63,13 +63,20 @@ class TelepathyClient(dbus.service.Object, DBusProperties):
     def __get_filters_cb(self):
         logging.debug('__get_filters_cb')
 
-        filt = {
+        activity_invitation = {
             CHANNEL + '.ChannelType': CHANNEL_TYPE_TEXT,
             CHANNEL + '.TargetHandleType': CONNECTION_HANDLE_TYPE_ROOM,
             }
-        filter_dict = dbus.Dictionary(filt, signature='sv')
+        filter_dict = dbus.Dictionary(activity_invitation, signature='sv')
         filters = dbus.Array([filter_dict], signature='a{sv}')
 
+        text_invitation = {
+            CHANNEL + '.ChannelType': CHANNEL_TYPE_TEXT,
+            CHANNEL + '.TargetHandleType': CONNECTION_HANDLE_TYPE_CONTACT,
+            }
+        filter_dict = dbus.Dictionary(text_invitation, signature='sv')
+        filters.append(filter_dict)
+
         logging.debug('__get_filters_cb %r', filters)
 
         return filters
-- 
1.7.4



More information about the Sugar-devel mailing list