More fixes for sharing activities
This commit is contained in:
parent
97881ae7c0
commit
9034dc8f3b
@ -8,8 +8,12 @@ import urllib
|
|||||||
from sugar.shell import activity
|
from sugar.shell import activity
|
||||||
from sugar.browser import NotificationBar
|
from sugar.browser import NotificationBar
|
||||||
from sugar.browser import NavigationToolbar
|
from sugar.browser import NavigationToolbar
|
||||||
|
from sugar.presence.PresenceService import PresenceService
|
||||||
|
|
||||||
|
|
||||||
_BROWSER_ACTIVITY_TYPE = "_web_browser_olpc._udp"
|
_BROWSER_ACTIVITY_TYPE = "_web_browser_olpc._udp"
|
||||||
|
_SERVICE_URI_TAG = "URI"
|
||||||
|
_SERVICE_TITLE_TAG = "Title"
|
||||||
|
|
||||||
class BrowserActivity(activity.Activity):
|
class BrowserActivity(activity.Activity):
|
||||||
SOLO = 1
|
SOLO = 1
|
||||||
@ -20,6 +24,11 @@ class BrowserActivity(activity.Activity):
|
|||||||
activity.Activity.__init__(self)
|
activity.Activity.__init__(self)
|
||||||
self.uri = uri
|
self.uri = uri
|
||||||
self._mode = BrowserActivity.SOLO
|
self._mode = BrowserActivity.SOLO
|
||||||
|
self._pservice = PresenceService.get_instance()
|
||||||
|
self._pservice.start()
|
||||||
|
self._pservice.track_service_type(_BROWSER_ACTIVITY_TYPE)
|
||||||
|
self._share_service = None
|
||||||
|
self._model = None
|
||||||
|
|
||||||
def _update_shared_location(self):
|
def _update_shared_location(self):
|
||||||
address = self.embed.get_address()
|
address = self.embed.get_address()
|
||||||
@ -46,10 +55,11 @@ class BrowserActivity(activity.Activity):
|
|||||||
self._notif_bar.show()
|
self._notif_bar.show()
|
||||||
|
|
||||||
def _setup_shared(self, uri):
|
def _setup_shared(self, uri):
|
||||||
self._model = self._group.get_store().get_model(uri)
|
if False:
|
||||||
if self._model:
|
self._model = self._group.get_store().get_model(uri)
|
||||||
self.set_mode(BrowserActivity.FOLLOWING)
|
if self._model:
|
||||||
self._model.add_listener(self.__shared_location_changed_cb)
|
self.set_mode(BrowserActivity.FOLLOWING)
|
||||||
|
self._model.add_listener(self.__shared_location_changed_cb)
|
||||||
|
|
||||||
def on_connected_to_shell(self):
|
def on_connected_to_shell(self):
|
||||||
self.set_ellipsize_tab(True)
|
self.set_ellipsize_tab(True)
|
||||||
@ -90,20 +100,27 @@ class BrowserActivity(activity.Activity):
|
|||||||
return self.embed
|
return self.embed
|
||||||
|
|
||||||
def share(self):
|
def share(self):
|
||||||
url = self.embed.get_address()
|
|
||||||
self._model = self._group.get_store().create_model(url)
|
|
||||||
self._model.set_value('owner', self._group.get_owner().get_nick_name())
|
|
||||||
self._update_shared_location()
|
|
||||||
self.set_mode(BrowserActivity.LEADING)
|
|
||||||
|
|
||||||
bus = dbus.SessionBus()
|
|
||||||
proxy_obj = bus.get_object('com.redhat.Sugar.Chat', '/com/redhat/Sugar/Chat')
|
|
||||||
chat_shell = dbus.Interface(proxy_obj, 'com.redhat.Sugar.ChatShell')
|
|
||||||
|
|
||||||
escaped_title = urllib.quote(self.embed.get_title())
|
escaped_title = urllib.quote(self.embed.get_title())
|
||||||
escaped_url = urllib.quote(url)
|
escaped_url = urllib.quote(self.embed.get_address())
|
||||||
chat_shell.send_text_message('<richtext><link href="' + escaped_address +
|
|
||||||
'">' + escaped_title + '</link></richtext>')
|
# Publish ourselves on the network
|
||||||
|
properties = {_SERVICE_URI_TAG: escaped_url, _SERVICE_TITLE_TAG: escaped_title}
|
||||||
|
self._share_service = self._pservice.share_activity(self,
|
||||||
|
stype=_BROWSER_ACTIVITY_TYPE, properties=properties)
|
||||||
|
|
||||||
|
if False:
|
||||||
|
# Create our activity-specific browser sharing service
|
||||||
|
self._model = self._group.get_store().create_model(url)
|
||||||
|
self._model.set_value('owner', self._pservice.get_owner().get_nick_name())
|
||||||
|
self._update_shared_location()
|
||||||
|
self.set_mode(BrowserActivity.LEADING)
|
||||||
|
|
||||||
|
bus = dbus.SessionBus()
|
||||||
|
proxy_obj = bus.get_object('com.redhat.Sugar.Chat', '/com/redhat/Sugar/Chat')
|
||||||
|
chat_shell = dbus.Interface(proxy_obj, 'com.redhat.Sugar.ChatShell')
|
||||||
|
|
||||||
|
chat_shell.send_text_message('<richtext><link href="' + escaped_address +
|
||||||
|
'">' + escaped_title + '</link></richtext>')
|
||||||
|
|
||||||
def __title_cb(self, embed):
|
def __title_cb(self, embed):
|
||||||
self.set_tab_text(embed.get_title())
|
self.set_tab_text(embed.get_title())
|
||||||
|
@ -4,6 +4,7 @@ import Buddy
|
|||||||
import Service
|
import Service
|
||||||
import os
|
import os
|
||||||
import string
|
import string
|
||||||
|
import random
|
||||||
from sugar import util
|
from sugar import util
|
||||||
|
|
||||||
def _get_local_ip_address(ifname):
|
def _get_local_ip_address(ifname):
|
||||||
@ -164,8 +165,6 @@ class PresenceService(gobject.GObject):
|
|||||||
if domain and adv.domain() != domain:
|
if domain and adv.domain() != domain:
|
||||||
continue
|
continue
|
||||||
adv_list.append(adv)
|
adv_list.append(adv)
|
||||||
if not len(adv_list):
|
|
||||||
return None
|
|
||||||
return adv_list
|
return adv_list
|
||||||
|
|
||||||
def _is_special_service_type(self, stype):
|
def _is_special_service_type(self, stype):
|
||||||
@ -191,6 +190,7 @@ class PresenceService(gobject.GObject):
|
|||||||
if service.get_address() in self._local_addrs.values():
|
if service.get_address() in self._local_addrs.values():
|
||||||
buddy = Buddy.Owner(service)
|
buddy = Buddy.Owner(service)
|
||||||
self._owner = buddy
|
self._owner = buddy
|
||||||
|
print "Set owner to %s" % name
|
||||||
else:
|
else:
|
||||||
buddy = Buddy.Buddy(service)
|
buddy = Buddy.Buddy(service)
|
||||||
self._buddies[name] = buddy
|
self._buddies[name] = buddy
|
||||||
@ -200,7 +200,7 @@ class PresenceService(gobject.GObject):
|
|||||||
|
|
||||||
def _handle_new_service_for_activity(self, service, buddy):
|
def _handle_new_service_for_activity(self, service, buddy):
|
||||||
# If the serivce is a group service, merge it into our groups list
|
# If the serivce is a group service, merge it into our groups list
|
||||||
uid = service.get_activity_uid()
|
(uid, ignore) = service.get_activity_uid()
|
||||||
if not uid:
|
if not uid:
|
||||||
uid = "*"
|
uid = "*"
|
||||||
if not self._activity_services.has_key(uid):
|
if not self._activity_services.has_key(uid):
|
||||||
@ -208,7 +208,7 @@ class PresenceService(gobject.GObject):
|
|||||||
self._activity_services[uid].append((buddy, service))
|
self._activity_services[uid].append((buddy, service))
|
||||||
|
|
||||||
def _handle_remove_service_for_activity(self, service, buddy):
|
def _handle_remove_service_for_activity(self, service, buddy):
|
||||||
uid = service.get_activity_uid()
|
(uid, ignore) = service.get_activity_uid()
|
||||||
if not uid:
|
if not uid:
|
||||||
uid = "*"
|
uid = "*"
|
||||||
if self._activity_services.has_key(uid):
|
if self._activity_services.has_key(uid):
|
||||||
@ -238,7 +238,8 @@ class PresenceService(gobject.GObject):
|
|||||||
|
|
||||||
# Merge the service into our buddy and group lists, if needed
|
# Merge the service into our buddy and group lists, if needed
|
||||||
buddy = self._handle_new_service_for_buddy(service)
|
buddy = self._handle_new_service_for_buddy(service)
|
||||||
if buddy and service.get_activity_uid():
|
(uid, ignore) = service.get_activity_uid()
|
||||||
|
if buddy and uid:
|
||||||
self._handle_new_service_for_activity(service, buddy)
|
self._handle_new_service_for_activity(service, buddy)
|
||||||
|
|
||||||
return False
|
return False
|
||||||
@ -376,8 +377,11 @@ class PresenceService(gobject.GObject):
|
|||||||
a certain mDNS service types."""
|
a certain mDNS service types."""
|
||||||
if not self._started:
|
if not self._started:
|
||||||
raise RuntimeError("presence service must be started first.")
|
raise RuntimeError("presence service must be started first.")
|
||||||
if not type(stype) == type(""):
|
print "about to track type %s" % stype
|
||||||
|
if type(stype) != type("") and type(stype) != type(u""):
|
||||||
raise ValueError("service type must be a string.")
|
raise ValueError("service type must be a string.")
|
||||||
|
if type(stype) == type(u""):
|
||||||
|
stype = stype.encode()
|
||||||
if self._is_special_service_type(stype):
|
if self._is_special_service_type(stype):
|
||||||
return
|
return
|
||||||
if stype in self._allowed_service_types:
|
if stype in self._allowed_service_types:
|
||||||
@ -423,7 +427,7 @@ class PresenceService(gobject.GObject):
|
|||||||
"""Convenience function to share an activity with other buddies."""
|
"""Convenience function to share an activity with other buddies."""
|
||||||
uid = activity.get_id()
|
uid = activity.get_id()
|
||||||
owner_nick = self._owner.get_nick_name()
|
owner_nick = self._owner.get_nick_name()
|
||||||
real_stype = "_%s_%s" % (uid, stype)
|
real_stype = Service.compose_service_type(stype, uid)
|
||||||
if address and type(address) != type(""):
|
if address and type(address) != type(""):
|
||||||
raise ValueError("address must be a valid string.")
|
raise ValueError("address must be a valid string.")
|
||||||
if not address:
|
if not address:
|
||||||
@ -449,7 +453,7 @@ class PresenceService(gobject.GObject):
|
|||||||
raise RuntimeError("presence service must be started first.")
|
raise RuntimeError("presence service must be started first.")
|
||||||
|
|
||||||
rs_name = service.get_name()
|
rs_name = service.get_name()
|
||||||
rs_stype = service.get_network_type()
|
rs_stype = service.get_type()
|
||||||
rs_port = service.get_port()
|
rs_port = service.get_port()
|
||||||
if type(rs_port) != type(1) and (rs_port <= 1024 or rs_port > 65536):
|
if type(rs_port) != type(1) and (rs_port <= 1024 or rs_port > 65536):
|
||||||
raise ValueError("invalid service port.")
|
raise ValueError("invalid service port.")
|
||||||
@ -472,7 +476,8 @@ class PresenceService(gobject.GObject):
|
|||||||
# should un-register it an re-register with the correct info
|
# should un-register it an re-register with the correct info
|
||||||
if str(exc) == "Local name collision":
|
if str(exc) == "Local name collision":
|
||||||
pass
|
pass
|
||||||
self.track_service_type(service.get_network_type())
|
(uid, activity_stype) = service.get_activity_uid()
|
||||||
|
self.track_service_type(activity_stype)
|
||||||
return group
|
return group
|
||||||
|
|
||||||
def get_buddy_by_nick_name(self, nick_name):
|
def get_buddy_by_nick_name(self, nick_name):
|
||||||
|
@ -41,6 +41,9 @@ def _txt_to_dict(txt):
|
|||||||
prop_dict[key] = value
|
prop_dict[key] = value
|
||||||
return prop_dict
|
return prop_dict
|
||||||
|
|
||||||
|
def compose_service_type(stype, activity_uid):
|
||||||
|
return "_%s_%s" % (activity_uid, stype)
|
||||||
|
|
||||||
def _decompose_service_type(stype):
|
def _decompose_service_type(stype):
|
||||||
"""Break a service type into the UID and real service type, if we can."""
|
"""Break a service type into the UID and real service type, if we can."""
|
||||||
if len(stype) < util.ACTIVITY_UID_LEN + 5:
|
if len(stype) < util.ACTIVITY_UID_LEN + 5:
|
||||||
@ -54,7 +57,7 @@ def _decompose_service_type(stype):
|
|||||||
uid = stype[start:end]
|
uid = stype[start:end]
|
||||||
if not util.validate_activity_uid(uid):
|
if not util.validate_activity_uid(uid):
|
||||||
return (None, stype)
|
return (None, stype)
|
||||||
return (uid, stype[end:])
|
return (uid, stype[end+1:])
|
||||||
|
|
||||||
def is_multicast_address(address):
|
def is_multicast_address(address):
|
||||||
"""Simple numerical check for whether an IP4 address
|
"""Simple numerical check for whether an IP4 address
|
||||||
@ -89,13 +92,19 @@ class Service(object):
|
|||||||
if len(domain) and domain != "local" and domain != u"local":
|
if len(domain) and domain != "local" and domain != u"local":
|
||||||
raise ValueError("must use the 'local' domain (for now).")
|
raise ValueError("must use the 'local' domain (for now).")
|
||||||
|
|
||||||
|
if type(stype) == type(u""):
|
||||||
|
stype = stype.encode()
|
||||||
(uid, real_stype) = _decompose_service_type(stype)
|
(uid, real_stype) = _decompose_service_type(stype)
|
||||||
if uid and not util.validate_activity_uid(activity_uid):
|
if uid and not util.validate_activity_uid(uid):
|
||||||
raise ValueError("activity_uid not a valid activity UID.")
|
raise ValueError("service type activity uid not a valid activity UID.")
|
||||||
|
|
||||||
|
if type(name) == type(u""):
|
||||||
|
name = name.encode()
|
||||||
self._name = name
|
self._name = name
|
||||||
self._stype = stype
|
self._stype = stype
|
||||||
self._real_stype = real_stype
|
self._activity_stype = real_stype
|
||||||
|
if type(domain) == type(u""):
|
||||||
|
domain = domain.encode()
|
||||||
self._domain = domain
|
self._domain = domain
|
||||||
self._address = None
|
self._address = None
|
||||||
self.set_address(address)
|
self.set_address(address)
|
||||||
@ -147,15 +156,14 @@ class Service(object):
|
|||||||
self._properties = _txt_to_dict(properties)
|
self._properties = _txt_to_dict(properties)
|
||||||
elif type(properties) == type({}):
|
elif type(properties) == type({}):
|
||||||
self._properties = properties
|
self._properties = properties
|
||||||
|
for key, value in self._properties.items():
|
||||||
|
if type(self._properties[key]) == type(u""):
|
||||||
|
self._properties[key] = self._properties[key].encode()
|
||||||
|
|
||||||
def get_type(self):
|
def get_type(self):
|
||||||
"""Return the service's service type."""
|
"""Return the service's service type."""
|
||||||
return self._stype
|
return self._stype
|
||||||
|
|
||||||
def get_network_type(self):
|
|
||||||
"""Return the full service type, including activity UID."""
|
|
||||||
return self._real_stype
|
|
||||||
|
|
||||||
def get_port(self):
|
def get_port(self):
|
||||||
return self._port
|
return self._port
|
||||||
|
|
||||||
@ -173,6 +181,8 @@ class Service(object):
|
|||||||
raise ValueError("must specify a valid address.")
|
raise ValueError("must specify a valid address.")
|
||||||
if not len(address):
|
if not len(address):
|
||||||
raise ValueError("must specify a valid address.")
|
raise ValueError("must specify a valid address.")
|
||||||
|
if address and type(address) == type(u""):
|
||||||
|
address = address.encode()
|
||||||
self._address = address
|
self._address = address
|
||||||
|
|
||||||
def get_domain(self):
|
def get_domain(self):
|
||||||
@ -181,7 +191,7 @@ class Service(object):
|
|||||||
|
|
||||||
def get_activity_uid(self):
|
def get_activity_uid(self):
|
||||||
"""Return the activity UID this service is associated with, if any."""
|
"""Return the activity UID this service is associated with, if any."""
|
||||||
return self._activity_uid
|
return (self._activity_uid, self._activity_stype)
|
||||||
|
|
||||||
|
|
||||||
#################################################################
|
#################################################################
|
||||||
|
Loading…
Reference in New Issue
Block a user