This commit is contained in:
Marco Pesenti Gritti 2006-06-15 11:29:00 -04:00
parent f0af49616c
commit 27b4f25fad
9 changed files with 76 additions and 28 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -1,25 +1,24 @@
from xml.sax import saxutils
import dbus
import pygtk
pygtk.require('2.0')
import gtk
import geckoembed
import urllib
from sugar.shell import activity
from sugar.browser import NotificationBar
from sugar.browser import NavigationToolbar
_BROWSER_ACTIVITY_TYPE = "_web_browser_olpc._udp"
class BrowserActivity(activity.Activity):
SOLO = 1
FOLLOWING = 2
LEADING = 3
def __init__(self, group, uri):
def __init__(self, uri):
activity.Activity.__init__(self)
self.uri = uri
self._group = group
self._mode = BrowserActivity.SOLO
def _update_shared_location(self):
@ -85,14 +84,14 @@ class BrowserActivity(activity.Activity):
self._setup_shared(self.uri)
def publish(self):
print 'Publish %s' % self.activity_get_id()
print 'Publish %s' % self.get_id()
def get_embed(self):
return self.embed
def share(self):
address = self.embed.get_address()
self._model = self._group.get_store().create_model(address)
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)
@ -101,8 +100,8 @@ class BrowserActivity(activity.Activity):
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 = saxutils.escape(self.embed.get_title())
escaped_address = saxutils.escape(address)
escaped_title = urllib.quote(self.embed.get_title())
escaped_url = urllib.quote(url)
chat_shell.send_text_message('<richtext><link href="' + escaped_address +
'">' + escaped_title + '</link></richtext>')

View File

@ -31,6 +31,6 @@ class BrowserShell(dbus.service.Object):
@dbus.service.method('com.redhat.Sugar.BrowserShell')
def open_browser(self, uri):
browser = BrowserActivity(None, uri)
browser = BrowserActivity(uri)
self.__browsers.append(browser)
browser.connect_to_shell()

View File

@ -10,6 +10,12 @@ import pygtk
pygtk.require('2.0')
import gtk, gobject, pango
from sugar.shell import activity
from sugar.presence import Buddy
from sugar.presence.Service import Service
from sugar.p2p.Stream import Stream
from sugar.p2p import network
from sugar.session.LogWriter import LogWriter
from sugar.chat.sketchpad.Toolbox import Toolbox
from sugar.chat.sketchpad.SketchPad import SketchPad
from sugar.chat.Emoticons import Emoticons

View File

@ -111,13 +111,13 @@ class PresenceService(gobject.GObject):
self._service_advs = []
# Main activity UID to filter services on
self._activity_uid = None
self._activity_uids = []
self._bus = dbus.SystemBus()
self._server = dbus.Interface(self._bus.get_object(avahi.DBUS_NAME,
avahi.DBUS_PATH_SERVER), avahi.DBUS_INTERFACE_SERVER)
def start(self, activity_uid=None):
def start(self):
"""Start the presence service by kicking off service discovery."""
self._lock.acquire()
if self._started:
@ -126,10 +126,6 @@ class PresenceService(gobject.GObject):
self._started = True
self._lock.release()
if activity_uid and not util.validate_activity_uid(activity_uid):
raise ValueError("activity uid must be a valid UID string.")
self._activity_uid = activity_uid
# Always browse .local
self._new_domain_cb(avahi.IF_UNSPEC, avahi.PROTO_UNSPEC, "local")
@ -284,11 +280,9 @@ class PresenceService(gobject.GObject):
# If we care about the service right now, resolve it
resolve = False
if self._activity_uid and self._activity_uid == uid:
if uid in self._activity_uids:
if stype in self._allowed_service_types:
resolve = True
elif not self._activity_uid:
resolve = True
if self._is_special_service_type(stype):
resolve = True
if resolve:
@ -389,6 +383,11 @@ class PresenceService(gobject.GObject):
if stype in self._allowed_service_types:
return
# Decompose service type if we can
(uid, stype) = Service._decompose_service_type(stype)
if uid and util.validate_activity_uid(uid):
if uid not in self._activity_uids:
self._activity_uids.append(uid)
self._allowed_service_types.append(stype)
# Find unresolved services that match the service type
@ -404,24 +403,53 @@ class PresenceService(gobject.GObject):
raise RuntimeError("presence service must be started first.")
if not type(stype) == type(""):
raise ValueError("service type must be a string.")
if name in self._allowed_service_types:
# Decompose service type if we can
(uid, stype) = Service._decompose_service_type(stype)
if uid and util.validate_activity_uid(uid):
if uid in self._activity_uids:
self._activity_uids.remove(uid)
if stype in self._allowed_service_types:
self._allowed_service_types.remove(stype)
def join_group(self, group):
def join_shared_activity(self, service):
"""Convenience function to join a group and notify other buddies
that you are a member of it."""
if not isinstance(group, Group.Group):
raise ValueError("group was not a valid group.")
gservice = group.get_service()
if not isinstance(service, Service.Service):
raise ValueError("service was not a valid service object.")
self.register_service(service)
def share_activity(self, activity, stype, properties={}, address=None, port=None):
"""Convenience function to share an activity with other buddies."""
uid = activity.get_id()
owner_nick = self._owner.get_nick_name()
real_stype = "_%s_%s" % (uid, stype)
if address and type(address) != type(""):
raise ValueError("address must be a valid string.")
if not address:
# Use random currently unassigned multicast address
address = "232.%d.%d.%d" % (random.randint(0, 254), random.randint(1, 254),
random.randint(1, 254))
if port and (type(port) != type(1) or port <= 1024 or port >= 65535):
raise ValueError("port must be a number between 1024 and 65535")
if not port:
# random port #
port = random.randint(5000, 65535)
service = Service.Service(name=owner_nick, stype=real_stype, domain="local",
address=address, port=port, properties=properties)
# Publish it to the world
self.register_service(service)
return service
def register_service(self, service):
"""Register a new service, advertising it to other Buddies on the network."""
if not self._started:
raise RuntimeError("presence service must be started first.")
rs_name = service.get_name()
rs_stype = service.get_type()
rs_stype = service.get_network_type()
rs_port = service.get_port()
if type(rs_port) != type(1) and (rs_port <= 1024 or rs_port > 65536):
raise ValueError("invalid service port.")
@ -444,7 +472,7 @@ class PresenceService(gobject.GObject):
# should un-register it an re-register with the correct info
if str(exc) == "Local name collision":
pass
self.track_service_type(rs_stype)
self.track_service_type(service.get_network_type())
return group
def get_buddy_by_nick_name(self, nick_name):

View File

@ -69,6 +69,8 @@ def is_multicast_address(address):
return False
_ACTIVITY_UID_TAG = "ActivityUID"
class Service(object):
"""Encapsulates information about a specific ZeroConf/mDNS
service as advertised on the network."""
@ -101,7 +103,16 @@ class Service(object):
self.set_port(port)
self._properties = {}
self.set_properties(properties)
# Ensure that an ActivityUID tag, if given, matches
# what we expect from the service type
if self._properties.has_key(_ACTIVITY_UID_TAG):
prop_uid = self._properties[_ACTIVITY_UID_TAG]
if (prop_uid and not uid) or (prop_uid != uid):
raise ValueError("ActivityUID property specified, but the service type's activity UID didn't match it.")
self._activity_uid = uid
if uid and not self._properties.has_key(_ACTIVITY_UID_TAG):
self._properties[_ACTIVITY_UID_TAG] = uid
def get_name(self):
"""Return the service's name, usually that of the
@ -141,6 +152,10 @@ class Service(object):
"""Return the service's service type."""
return self._stype
def get_network_type(self):
"""Return the full service type, including activity UID."""
return self._real_stype
def get_port(self):
return self._port

View File

@ -268,7 +268,7 @@ class Activity(object):
else:
self._activity_object.set_has_changes(False)
def activity_get_id(self):
def get_id(self):
return self._activity_id
def shutdown(self):