Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAleksey Lim <alsroot@sugarlabs.org>2012-07-23 09:46:37 (GMT)
committer Aleksey Lim <alsroot@sugarlabs.org>2012-07-23 09:46:37 (GMT)
commitc869ea9e4b0f0d2a35174e727b563bfc9160b81b (patch)
tree96a910dcdeda4f1b947bcf15abb2eab5c849a74c
parentc0326e3f93f14425a0005d42f38017c30c8d0feb (diff)
Switch to DBus SN interface
-rw-r--r--plugin/__init__.py61
-rw-r--r--plugin/browser.py4
-rw-r--r--plugin/bundleregistry.py87
-rw-r--r--plugin/launcher.py17
4 files changed, 112 insertions, 57 deletions
diff --git a/plugin/__init__.py b/plugin/__init__.py
index 5fe5cf7..61ede76 100644
--- a/plugin/__init__.py
+++ b/plugin/__init__.py
@@ -13,14 +13,16 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
-import os
+import json
+import logging
import subprocess
from gettext import gettext as _
+import dbus
import gobject
from sugar.graphics.alert import NotifyAlert, ErrorAlert
-from sugar_network import sugar, GlibClient, api_url, server_mode
+from sugar_network import sugar, api_url, server_mode
from active_toolkit.options import Option
@@ -42,6 +44,7 @@ _ALERT_SEVERITIES = {
None: (NotifyAlert, _('Sugar Network')),
}
+_logger = logging.getLogger('plugins.sn')
_bundleregistry = None
_launcher = None
_client = None
@@ -62,10 +65,6 @@ def init():
api_url.value = SN_MASER_URL
Option.save()
- if not os.fork():
- args = ['sugar-network-service', '--webui', '--delayed-start', 'start']
- os.execvp(args[0], args)
-
import jarabe.model.bundleregistry
from .bundleregistry import BundleRegistry
@@ -81,15 +80,11 @@ def init():
def enable():
- global _launcher, _client
+ global _launcher
if not sugar_network.value:
return
- _client = GlibClient()
- _client.connect('alert',
- lambda sender, severity, message: add_alert(severity, msg=message))
-
_bundleregistry.populate()
from jarabe.journal import misc
@@ -102,7 +97,7 @@ def enable():
shell = get_model()
def delayed_start():
- _client.publish('delayed-start')
+ get_client().Publish({'event': 'delayed-start'})
get_browser()
def activity_added_cb(model, activity):
@@ -122,6 +117,11 @@ def get_registry():
def get_client():
+ global _client
+
+ if _client is None:
+ _client = _Client()
+
return _client
@@ -171,3 +171,40 @@ def _get_bundle_path(self):
for env in f.read().split('\0'):
if env.startswith('SUGAR_BUNDLE_PATH='):
return env.split('=', 1)[-1]
+
+
+class _Client(object):
+
+ def __init__(self):
+ self._event_callbacks = []
+ self._client = dbus.Interface(
+ dbus.SessionBus().get_object(
+ 'org.sugarlabs.Network',
+ '/org/sugarlabs/Network'),
+ 'org.sugarlabs.Network')
+ self._client.connect_to_signal('Event', self.__Event_cb)
+
+ def connect_to_signal(self, signal, callback):
+ if signal == 'Event':
+ self._event_callbacks.append(callback)
+ else:
+ return self._client.connect_to_signal(signal, callback)
+
+ def __getattr__(self, name):
+ return getattr(self._client, name)
+
+ def __Event_cb(self, event):
+ event = json.loads(event)
+
+ for callback in self._event_callbacks:
+ try:
+ callback(event)
+ except Exception:
+ _logger.exception('%r callback failed on %r SN event',
+ callback, event)
+
+ event_type = event.get('event')
+ if event.get('event') == 'alert':
+ add_alert(event['severity'], msg=event['message'])
+ elif event_type == 'sync_complete':
+ add_alert('info', msg=_('Synchronization completed'))
diff --git a/plugin/browser.py b/plugin/browser.py
index 68a406c..58a987d 100644
--- a/plugin/browser.py
+++ b/plugin/browser.py
@@ -65,7 +65,7 @@ class Browser(Window):
self.show_all()
self._webkit.connect('notify::load-status', self.__load_status_cb)
- get_client().connect('connect', self.__connection_cb)
+ get_client().connect_to_signal('Event', self.__Event_cb)
gobject.timeout_add_seconds(_RETRY_TIMEOUT, self._open)
@@ -105,7 +105,7 @@ class Browser(Window):
wm.set_activity_id(window.window, create_activity_id())
self.disconnect_by_func(self.__realize_cb)
- def __connection_cb(self, sender, mountpoint, connected):
+ def __Event_cb(self, event):
self._open()
diff --git a/plugin/bundleregistry.py b/plugin/bundleregistry.py
index d4ca5f8..3f9bb36 100644
--- a/plugin/bundleregistry.py
+++ b/plugin/bundleregistry.py
@@ -15,14 +15,13 @@
import os
import logging
-from os.path import lexists, basename
+from os.path import lexists
from gettext import gettext as _
import gtk
import gobject
-import sugar_network
-from sugar.util import LRU
+from sugar_network import checkins, sugar
from sugar.bundle.activitybundle import ActivityBundle
from jarabe.plugins.sn import SN_BROWSER_NAME, get_client
@@ -30,7 +29,6 @@ from jarabe.plugins.sn import SN_BROWSER_NAME, get_client
_logger = logging.getLogger('plugins.sn.bundleregistry')
_stub_icon_path = None
-_online_cache = LRU(100)
class BundleRegistry(gobject.GObject):
@@ -51,15 +49,21 @@ class BundleRegistry(gobject.GObject):
def populate(self):
client = get_client()
+ client.connect_to_signal('Event', self.__Event_cb)
- for props in client.find('~', 'context', 0, 50,
- reply=['guid', 'keep', 'keep_impl', 'position']):
- if props['keep_impl']:
+ def reply_handler(entries, total):
+ for props in entries:
bundle = self._add_bundle(props['guid'], props)
- self.emit('bundle-added', bundle)
+ if bundle is not None:
+ self.emit('bundle-added', bundle)
+
+ def error_handler(error):
+ _logger.warning('Cannot call Find(): %s', error)
- client.connect('keep', self.__keep_cb)
- client.connect('keep_impl', self.__keep_impl_cb)
+ client.Find('~', 'context',
+ ['guid', 'keep', 'keep_impl', 'position'],
+ {'keep_impl': 2, 'limit': 1024},
+ reply_handler=reply_handler, error_handler=error_handler)
def __iter__(self):
return self._bundles.itervalues()
@@ -76,22 +80,17 @@ class BundleRegistry(gobject.GObject):
if context_guid in self._bundles:
return self._bundles[context_guid]
- if context_guid in _online_cache:
- return _online_cache[context_guid]
-
if mountpoint == '~':
return None
-
try:
- props = get_client().get(mountpoint, 'context', context_guid,
- reply=['guid', 'keep', 'keep_impl', 'title'])
+ props = get_client().Get(mountpoint, 'context', context_guid,
+ ['guid', 'keep', 'keep_impl', 'title'])
result = _ContextInfo(mountpoint, props)
except Exception:
- _logger.warning(_('Cannot fetch activity metadata'))
+ _logger.warning('Cannot fetch activity metadata for %r on %r',
+ context_guid, mountpoint)
result = None
- _online_cache[context_guid] = result
-
return result
def get_activities_for_type(self, mime_type):
@@ -112,7 +111,7 @@ class BundleRegistry(gobject.GObject):
bundle = self._bundles.get(bundle_id)
if bundle is None:
return
- get_client().update('~', 'context', bundle_id, keep=keep)
+ get_client().Update('~', 'context', bundle_id, {'keep': keep})
bundle.props['keep'] = keep
self.emit('bundle-changed', bundle)
@@ -127,7 +126,7 @@ class BundleRegistry(gobject.GObject):
if bundle is None:
return
position = bundle.props['position'] = [int(x), int(y)]
- get_client().update('~', 'context', bundle_id, position=position)
+ get_client().Update('~', 'context', bundle_id, {'position': position})
self.emit('bundle-changed', bundle)
def get_default_for_type(self, mime_type):
@@ -148,7 +147,7 @@ class BundleRegistry(gobject.GObject):
raise NotImplementedError('Not yet supported')
def _add_bundle(self, bundle_id, props):
- for path in sugar_network.checkins(bundle_id):
+ for path in checkins(bundle_id):
try:
bundle = self._bundles[bundle_id] = \
_BundleInfo(ActivityBundle(path), props)
@@ -160,28 +159,43 @@ class BundleRegistry(gobject.GObject):
else:
_logger.info('No bundles for %r', bundle_id)
- def __keep_cb(self, sender, bundle_id, keep):
+ def _set_keep(self, bundle_id, keep):
bundle = self._bundles.get(bundle_id)
if bundle is None:
return
bundle.props['keep'] = keep
self.emit('bundle-changed', bundle)
- def __keep_impl_cb(self, sender, bundle_id, keep_impl):
+ def _set_keep_impl(self, bundle_id, keep_impl):
if keep_impl:
- props = get_client().get('~', 'context', bundle_id,
- reply=['guid', 'keep', 'keep_impl', 'position'])
bundle = self._bundles.get(bundle_id)
if bundle is None:
+ props = get_client().Get('~', 'context', bundle_id,
+ ['guid', 'keep', 'keep_impl', 'position'])
bundle = self._add_bundle(bundle_id, props)
- else:
- bundle.props.update(props)
- self.emit('bundle-added', bundle)
+ if bundle is not None:
+ self.emit('bundle-added', bundle)
else:
if bundle_id in self._bundles:
bundle = self._bundles.pop(bundle_id)
self.emit('bundle-removed', bundle)
+ def __Event_cb(self, event):
+ if 'mountpoint' in event and event['mountpoint'] != '~' or \
+ event.get('document') != 'context':
+ return
+ event_type = event.get('event')
+ if event_type in ('create', 'update'):
+ bundle_id = event['guid']
+ props = event['props']
+ if props.get('keep_impl') in (0, 2):
+ self._set_keep_impl(bundle_id, props['keep_impl'])
+ if 'keep' in props:
+ self._set_keep(bundle_id, props['keep'])
+ elif event_type == 'delete':
+ bundle_id = event['guid']
+ self._set_keep_impl(bundle_id, 0)
+
class _ContextInfo(object):
@@ -196,21 +210,22 @@ class _ContextInfo(object):
return self.props['guid']
def get_icon(self):
- path = None
+ blob = None
try:
- path, __ = get_client().get_blob_path('/', 'context',
+ blob = get_client().GetBlob(self.mountpoint, 'context',
self.get_bundle_id(), 'artifact_icon')
except Exception, error:
_logger.debug('Fail to get icon for %r: %s',
self.get_bundle_id(), error)
- if not path or os.stat(path).st_size == 0:
+ if not blob or os.stat(blob['path']).st_size == 0:
return _stub_icon()
else:
- svg_path = path + '.svg'
- if not lexists(svg_path):
- os.symlink(basename(path), svg_path)
- return svg_path
+ path = sugar.profile_path('data', self.get_bundle_id() + '.svg')
+ if lexists(path):
+ os.unlink(path)
+ os.symlink(blob['path'], path)
+ return path
def get_tags(self):
# Doesn't matter with Sweets' features enabled
diff --git a/plugin/launcher.py b/plugin/launcher.py
index 08bb2f5..ea1ed76 100644
--- a/plugin/launcher.py
+++ b/plugin/launcher.py
@@ -42,7 +42,7 @@ class Launcher(object):
self._launches = {}
self._screen = wnck.screen_get_default()
self._screen.connect('window-opened', self.__window_opened_cb)
- get_client().connect('launch', self.__launch_cb)
+ get_client().connect_to_signal('Event', self.__Event_cb)
def launch(self, bundle, activity_id=None, object_id=None, uri=None,
color=None, invited=None, args=None):
@@ -141,14 +141,17 @@ class Launcher(object):
gtk.gdk.PROP_MODE_REPLACE, 'launcher')
wm.set_bundle_id(widget.window, str(bundle_id))
- def __launch_cb(self, sender, mountpoint, bundle_id, command, object_id,
- uri, args):
- bundle = get_registry().get_bundle(bundle_id, mountpoint)
+ def __Event_cb(self, event):
+ if event.get('event') != 'launch':
+ return
+ bundle = get_registry().get_bundle(
+ event['context'], event['mountpoint'])
if bundle is None:
- add_alert('error',
- msg=_('Cannot find %r activity to launch') % bundle_id)
+ add_alert('error', msg=_('Cannot find %s activity to launch') % \
+ event['context'])
else:
- self.launch(bundle, object_id=object_id, uri=uri, args=args)
+ self.launch(bundle, object_id=event['object_id'], uri=event['uri'],
+ args=event['args'])
def __progress_cb(self, source, cb_condition, pipe, activity_id):
event = pipe.read()