Merge
This commit is contained in:
parent
f0af49616c
commit
27b4f25fad
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -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>')
|
||||
|
||||
|
@ -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()
|
||||
|
@ -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
|
||||
|
@ -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):
|
||||
|
@ -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
|
||||
|
||||
|
@ -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):
|
||||
|
Loading…
Reference in New Issue
Block a user