Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMarco Pesenti Gritti <mpgritti@gmail.com>2008-10-06 13:54:46 (GMT)
committer Marco Pesenti Gritti <mpgritti@gmail.com>2008-10-06 13:54:46 (GMT)
commit5c6c7ab1d173d24ea0c72ff4337a08c313bd9761 (patch)
tree245394127a09685ad78a64870f7ef0ea5b86e1bc /src
parent0f33a634c0fc58ef61e6820dbf2cee382ab4d281 (diff)
The activity registry is now private to the shell.
Changed the activityfactory to take a bundle instead of a bundle_id so that it doesn't depend on the registry.
Diffstat (limited to 'src')
-rw-r--r--src/sugar/activity/Makefile.am3
-rw-r--r--src/sugar/activity/__init__.py3
-rw-r--r--src/sugar/activity/activityfactory.py139
-rw-r--r--src/sugar/activity/registry.py189
-rw-r--r--src/sugar/bundle/activitybundle.py68
5 files changed, 71 insertions, 331 deletions
diff --git a/src/sugar/activity/Makefile.am b/src/sugar/activity/Makefile.am
index 26a6782..ca1fa61 100644
--- a/src/sugar/activity/Makefile.am
+++ b/src/sugar/activity/Makefile.am
@@ -6,5 +6,4 @@ sugar_PYTHON = \
activityhandle.py \
activityservice.py \
bundlebuilder.py \
- main.py \
- registry.py
+ main.py
diff --git a/src/sugar/activity/__init__.py b/src/sugar/activity/__init__.py
index 8a984ad..8d3ef2b 100644
--- a/src/sugar/activity/__init__.py
+++ b/src/sugar/activity/__init__.py
@@ -53,6 +53,3 @@ class. This class allows for querying the ID of the root
window, requesting sharing across the network, and basic
"what type of application are you" queries.
"""
-from sugar.activity.registry import ActivityRegistry
-from sugar.activity.registry import get_registry
-from sugar.activity.registry import ActivityInfo
diff --git a/src/sugar/activity/activityfactory.py b/src/sugar/activity/activityfactory.py
index b9b2a44..8ba639b 100644
--- a/src/sugar/activity/activityfactory.py
+++ b/src/sugar/activity/activityfactory.py
@@ -23,7 +23,6 @@ import gobject
from sugar.presence import presenceservice
from sugar.activity.activityhandle import ActivityHandle
-from sugar.activity import registry
from sugar import util
from sugar import env
@@ -84,9 +83,9 @@ def create_activity_id():
def get_environment(activity):
environ = os.environ.copy()
- bin_path = os.path.join(activity.path, 'bin')
+ bin_path = os.path.join(activity.get_path(), 'bin')
- activity_root = env.get_profile_path(activity.bundle_id)
+ activity_root = env.get_profile_path(activity.get_bundle_id())
if not os.path.exists(activity_root):
os.mkdir(activity_root)
@@ -102,19 +101,19 @@ def get_environment(activity):
if not os.path.exists(tmp_dir):
os.mkdir(tmp_dir)
- environ['SUGAR_BUNDLE_PATH'] = activity.path
- environ['SUGAR_BUNDLE_ID'] = activity.bundle_id
+ environ['SUGAR_BUNDLE_PATH'] = activity.get_path()
+ environ['SUGAR_BUNDLE_ID'] = activity.get_bundle_id()
environ['SUGAR_ACTIVITY_ROOT'] = activity_root
environ['PATH'] = bin_path + ':' + environ['PATH']
#environ['RAINBOW_STRACE_LOG'] = '1'
- if activity.path.startswith(env.get_user_activities_path()):
- environ['SUGAR_LOCALEDIR'] = os.path.join(activity.path, 'locale')
+ if activity.get_path().startswith(env.get_user_activities_path()):
+ environ['SUGAR_LOCALEDIR'] = os.path.join(activity.get_path(), 'locale')
- if activity.bundle_id in [ 'org.laptop.WebActivity',
- 'org.laptop.GmailActivity',
- 'org.laptop.WikiBrowseActivity'
- ]:
+ if activity.get_bundle_id() in [ 'org.laptop.WebActivity',
+ 'org.laptop.GmailActivity',
+ 'org.laptop.WikiBrowseActivity'
+ ]:
environ['RAINBOW_CONSTANT_UID'] = 'yes'
return environ
@@ -123,8 +122,8 @@ def get_command(activity, activity_id=None, object_id=None, uri=None):
if not activity_id:
activity_id = create_activity_id()
- command = activity.command.split(' ')
- command.extend(['-b', activity.bundle_id])
+ command = activity.get_command().split(' ')
+ command.extend(['-b', activity.get_bundle_id()])
command.extend(['-a', activity_id])
if object_id is not None:
@@ -139,7 +138,7 @@ def get_command(activity, activity_id=None, object_id=None, uri=None):
def open_log_file(activity):
i = 1
while True:
- path = env.get_logs_path('%s-%s.log' % (activity.bundle_id, i))
+ path = env.get_logs_path('%s-%s.log' % (activity.get_bundle_id(), i))
try:
fd = os.open(path, os.O_EXCL | os.O_CREAT \
| os.O_SYNC | os.O_WRONLY, 0644)
@@ -164,10 +163,10 @@ class ActivityCreationHandler(gobject.GObject):
create call.
"""
- def __init__(self, service_name, handle):
+ def __init__(self, bundle, handle):
"""Initialise the handler
- service_name -- the service name of the bundle factory
+ bundle -- the ActivityBundle to launch
activity_handle -- stores the values which are to
be passed to the service to uniquely identify
the activity to be created and the sharing
@@ -190,15 +189,16 @@ class ActivityCreationHandler(gobject.GObject):
"""
gobject.GObject.__init__(self)
- self._service_name = service_name
+ self._bundle = bundle
+ self._service_name = bundle.get_bundle_id()
self._handle = handle
self._use_rainbow = os.path.exists('/etc/olpc-security')
- if service_name in [ 'org.laptop.JournalActivity',
- 'org.laptop.Terminal',
- 'org.laptop.Log',
- 'org.laptop.Analyze'
- ]:
+ if self._service_name in [ 'org.laptop.JournalActivity',
+ 'org.laptop.Terminal',
+ 'org.laptop.Log',
+ 'org.laptop.Analyze'
+ ]:
self._use_rainbow = False
bus = dbus.SessionBus()
@@ -233,49 +233,46 @@ class ActivityCreationHandler(gobject.GObject):
reply_handler=self._no_reply_handler,
error_handler=self._notify_launch_error_handler)
- activity_registry = registry.get_registry()
- activity = activity_registry.get_activity(self._service_name)
- if activity:
- environ = get_environment(activity)
- (log_path, log_file) = open_log_file(activity)
- command = get_command(activity, self._handle.activity_id,
- self._handle.object_id,
- self._handle.uri)
-
- if not self._use_rainbow:
- # use gobject spawn functionality, so that zombies are
- # automatically reaped by the gobject event loop.
- def child_setup():
- # clone logfile.fileno() onto stdout/stderr
- os.dup2(log_file.fileno(), 1)
- os.dup2(log_file.fileno(), 2)
- # close all other fds
- _close_fds()
- # we need to sanitize and str-ize the various bits which
- # dbus gives us.
- gobject.spawn_async([str(s) for s in command],
- envp=['%s=%s' % (k, str(v))
- for k, v in environ.items()],
- working_directory=str(activity.path),
- child_setup=child_setup,
- flags=(gobject.SPAWN_SEARCH_PATH |
- gobject.SPAWN_LEAVE_DESCRIPTORS_OPEN))
- log_file.close()
- else:
- log_file.close()
- system_bus = dbus.SystemBus()
- factory = system_bus.get_object(_RAINBOW_SERVICE_NAME,
- _RAINBOW_ACTIVITY_FACTORY_PATH)
- factory.CreateActivity(
- log_path,
- environ,
- command,
- environ['SUGAR_BUNDLE_PATH'],
- environ['SUGAR_BUNDLE_ID'],
- timeout=30,
- reply_handler=self._create_reply_handler,
- error_handler=self._create_error_handler,
- dbus_interface=_RAINBOW_ACTIVITY_FACTORY_INTERFACE)
+ environ = get_environment(self._bundle)
+ (log_path, log_file) = open_log_file(self._bundle)
+ command = get_command(self._bundle, self._handle.activity_id,
+ self._handle.object_id,
+ self._handle.uri)
+
+ if not self._use_rainbow:
+ # use gobject spawn functionality, so that zombies are
+ # automatically reaped by the gobject event loop.
+ def child_setup():
+ # clone logfile.fileno() onto stdout/stderr
+ os.dup2(log_file.fileno(), 1)
+ os.dup2(log_file.fileno(), 2)
+ # close all other fds
+ _close_fds()
+ # we need to sanitize and str-ize the various bits which
+ # dbus gives us.
+ gobject.spawn_async([str(s) for s in command],
+ envp=['%s=%s' % (k, str(v))
+ for k, v in environ.items()],
+ working_directory=str(self._bundle.get_path()),
+ child_setup=child_setup,
+ flags=(gobject.SPAWN_SEARCH_PATH |
+ gobject.SPAWN_LEAVE_DESCRIPTORS_OPEN))
+ log_file.close()
+ else:
+ log_file.close()
+ system_bus = dbus.SystemBus()
+ factory = system_bus.get_object(_RAINBOW_SERVICE_NAME,
+ _RAINBOW_ACTIVITY_FACTORY_PATH)
+ factory.CreateActivity(
+ log_path,
+ environ,
+ command,
+ environ['SUGAR_BUNDLE_PATH'],
+ environ['SUGAR_BUNDLE_ID'],
+ timeout=30,
+ reply_handler=self._create_reply_handler,
+ error_handler=self._create_error_handler,
+ dbus_interface=_RAINBOW_ACTIVITY_FACTORY_INTERFACE)
def _no_reply_handler(self, *args):
pass
@@ -315,18 +312,18 @@ class ActivityCreationHandler(gobject.GObject):
logging.error("Datastore find failed %s" % err)
self._create_activity()
-def create(service_name, activity_handle=None):
+def create(bundle, activity_handle=None):
"""Create a new activity from its name."""
if not activity_handle:
activity_handle = ActivityHandle()
- return ActivityCreationHandler(service_name, activity_handle)
+ return ActivityCreationHandler(bundle, activity_handle)
-def create_with_uri(service_name, uri):
+def create_with_uri(bundle, uri):
"""Create a new activity and pass the uri as handle."""
activity_handle = ActivityHandle(uri=uri)
- return ActivityCreationHandler(service_name, activity_handle)
+ return ActivityCreationHandler(bundle, activity_handle)
-def create_with_object_id(service_name, object_id):
+def create_with_object_id(bundle, object_id):
"""Create a new activity and pass the object id as handle."""
activity_handle = ActivityHandle(object_id=object_id)
- return ActivityCreationHandler(service_name, activity_handle)
+ return ActivityCreationHandler(bundle, activity_handle)
diff --git a/src/sugar/activity/registry.py b/src/sugar/activity/registry.py
deleted file mode 100644
index da2eb27..0000000
--- a/src/sugar/activity/registry.py
+++ /dev/null
@@ -1,189 +0,0 @@
-# Copyright (C) 2006-2007 Red Hat, Inc.
-# Copyright (C) 2007 One Laptop Per Child
-#
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of the GNU Lesser General Public
-# License as published by the Free Software Foundation; either
-# version 2 of the License, or (at your option) any later version.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the
-# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-# Boston, MA 02111-1307, USA.
-
-import logging
-
-import dbus
-import gobject
-
-_ACTIVITY_REGISTRY_SERVICE_NAME = 'org.laptop.ActivityRegistry'
-_ACTIVITY_REGISTRY_IFACE = 'org.laptop.ActivityRegistry'
-_ACTIVITY_REGISTRY_PATH = '/org/laptop/ActivityRegistry'
-
-def _activity_info_from_dict(info_dict):
- if not info_dict:
- return None
- return ActivityInfo(info_dict['name'], info_dict['icon'],
- info_dict['bundle_id'], info_dict['version'],
- info_dict['path'], info_dict['show_launcher'],
- info_dict['command'], info_dict['favorite'],
- info_dict['installation_time'],
- info_dict['position_x'], info_dict['position_y'])
-
-class ActivityInfo(object):
- def __init__(self, name, icon, bundle_id, version, path, show_launcher,
- command, favorite, installation_time, position_x, position_y):
- self.name = name
- self.icon = icon
- self.bundle_id = bundle_id
- self.version = version
- self.path = path
- self.command = command
- self.show_launcher = show_launcher
- self.favorite = favorite
- self.installation_time = installation_time
- self.position = (position_x, position_y)
-
-class ActivityRegistry(gobject.GObject):
- __gsignals__ = {
- 'activity-added': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
- ([gobject.TYPE_PYOBJECT])),
- 'activity-removed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
- ([gobject.TYPE_PYOBJECT])),
- 'activity-changed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
- ([gobject.TYPE_PYOBJECT]))
- }
- def __init__(self):
- gobject.GObject.__init__(self)
-
- bus = dbus.SessionBus()
-
- # NOTE: We need to follow_name_owner_changes here
- # because we can not connect to a signal unless
- # we follow the changes or we start the service
- # before we connect. Starting the service here
- # causes a major bottleneck during startup
- bus_object = bus.get_object(_ACTIVITY_REGISTRY_SERVICE_NAME,
- _ACTIVITY_REGISTRY_PATH,
- follow_name_owner_changes = True)
- self._registry = dbus.Interface(bus_object, _ACTIVITY_REGISTRY_IFACE)
- self._registry.connect_to_signal('ActivityAdded',
- self._activity_added_cb)
- self._registry.connect_to_signal('ActivityRemoved',
- self._activity_removed_cb)
- self._registry.connect_to_signal('ActivityChanged',
- self._activity_changed_cb)
-
- # Two caches fo saving some travel across dbus.
- self._service_name_to_activity_info = {}
- self._mime_type_to_activities = {}
-
- def _convert_info_list(self, info_list):
- result = []
-
- for info_dict in info_list:
- result.append(_activity_info_from_dict(info_dict))
-
- return result
-
- def get_activities(self):
- info_list = self._registry.GetActivities()
- return self._convert_info_list(info_list)
-
- def _get_activities_cb(self, reply_handler, info_list):
- result = []
- for info_dict in info_list:
- result.append(_activity_info_from_dict(info_dict))
-
- reply_handler(result)
-
- def _get_activities_error_cb(self, error_handler, e):
- if error_handler:
- error_handler(e)
- else:
- logging.error('Error getting activities async: %s' % str(e))
-
- def get_activities_async(self, reply_handler=None, error_handler=None):
- if not reply_handler:
- logging.error('Function get_activities_async called' \
- 'without a reply handler. Can not run.')
- return
-
- self._registry.GetActivities(
- reply_handler=lambda info_list: \
- self._get_activities_cb(reply_handler, info_list),
- error_handler=lambda e: \
- self._get_activities_error_cb(error_handler, e))
-
- def get_activity(self, service_name):
- if self._service_name_to_activity_info.has_key(service_name):
- return self._service_name_to_activity_info[service_name]
-
- info_dict = self._registry.GetActivity(service_name)
- activity_info = _activity_info_from_dict(info_dict)
-
- self._service_name_to_activity_info[service_name] = activity_info
- return activity_info
-
- def find_activity(self, name):
- info_list = self._registry.FindActivity(name)
- return self._convert_info_list(info_list)
-
- def get_activities_for_type(self, mime_type):
- if self._mime_type_to_activities.has_key(mime_type):
- return self._mime_type_to_activities[mime_type]
-
- info_list = self._registry.GetActivitiesForType(mime_type)
- activities = self._convert_info_list(info_list)
-
- self._mime_type_to_activities[mime_type] = activities
- return activities
-
- def add_bundle(self, bundle_path):
- result = self._registry.AddBundle(bundle_path)
- # Need to invalidate here because get_activity could be called after
- # add_bundle and before we receive activity-added, causing a race.
- self._invalidate_cache()
- return result
-
- def _activity_added_cb(self, info_dict):
- logging.debug('ActivityRegistry._activity_added_cb: invalidating cache')
- self._invalidate_cache()
- self.emit('activity-added', _activity_info_from_dict(info_dict))
-
- def _invalidate_cache(self):
- self._service_name_to_activity_info.clear()
- self._mime_type_to_activities.clear()
-
- def remove_bundle(self, bundle_path):
- self._invalidate_cache()
- return self._registry.RemoveBundle(bundle_path)
-
- def _activity_removed_cb(self, info_dict):
- logging.debug('ActivityRegistry._activity_removed_cb: flushing caches')
- self._invalidate_cache()
- self.emit('activity-removed', _activity_info_from_dict(info_dict))
-
- def _activity_changed_cb(self, info_dict):
- logging.debug('ActivityRegistry._activity_changed_cb: flushing caches')
- self._invalidate_cache()
- self.emit('activity-changed', _activity_info_from_dict(info_dict))
-
- def set_activity_favorite(self, bundle_id, version, favorite):
- self._registry.SetActivityFavorite(bundle_id, version, favorite)
-
- def set_activity_position(self, bundle_id, version, x, y):
- self._registry.SetActivityPosition(bundle_id, version, x, y)
-
-_registry = None
-
-def get_registry():
- global _registry
- if not _registry:
- _registry = ActivityRegistry()
- return _registry
diff --git a/src/sugar/bundle/activitybundle.py b/src/sugar/bundle/activitybundle.py
index 7097794..206eeb0 100644
--- a/src/sugar/bundle/activitybundle.py
+++ b/src/sugar/bundle/activitybundle.py
@@ -259,7 +259,6 @@ class ActivityBundle(Bundle):
return command
-
def get_mime_types(self):
"""Get the MIME types supported by the activity"""
return self._mime_types
@@ -268,22 +267,7 @@ class ActivityBundle(Bundle):
"""Get whether there should be a visible launcher for the activity"""
return self._show_launcher
- def is_installed(self):
- if activity.get_registry().get_activity(self._bundle_id):
- return True
- else:
- return False
-
- def need_upgrade(self):
- """Returns True if installing this activity bundle is meaningful -
- that is, if an identical version of this activity is not
- already installed.
-
- Until we have cryptographic hashes to check identity, returns
- True always. See http://dev.laptop.org/ticket/7534."""
- return True
-
- def unpack(self, install_dir, strict_manifest=False):
+ def install(self, install_dir, strict_manifest=False):
self._unzip(install_dir)
install_path = os.path.join(install_dir, self._zip_root_dir)
@@ -352,35 +336,7 @@ class ActivityBundle(Bundle):
os.path.basename(info_file)))
return install_path
- def install(self):
- activities_path = env.get_user_activities_path()
- act = activity.get_registry().get_activity(self._bundle_id)
- if act is not None and act.path.startswith(activities_path):
- raise AlreadyInstalledException
-
- install_dir = env.get_user_activities_path()
- install_path = self.unpack(install_dir)
-
- if not activity.get_registry().add_bundle(install_path):
- raise RegistrationException
-
- def uninstall(self, force=False):
- if self._zip_file is None:
- install_path = self._path
- else:
- if not self.is_installed():
- raise NotInstalledException
-
- act = activity.get_registry().get_activity(self._bundle_id)
- if not force and act.version != self._activity_version:
- logging.warning('Not uninstalling, different bundle present')
- return
- elif not act.path.startswith(env.get_user_activities_path()):
- logging.warning('Not uninstalling system activity')
- return
-
- install_path = act.path
-
+ def uninstall(self, install_path, force=False):
xdg_data_home = os.getenv('XDG_DATA_HOME',
os.path.expanduser('~/.local/share'))
@@ -404,23 +360,3 @@ class ActivityBundle(Bundle):
os.remove(path)
self._uninstall(install_path)
-
- if not activity.get_registry().remove_bundle(install_path):
- raise RegistrationException
-
- def upgrade(self):
- act = activity.get_registry().get_activity(self._bundle_id)
- if act is None:
- logging.warning('Activity not installed')
- elif act.path.startswith(env.get_user_activities_path()):
- try:
- self.uninstall(force=True)
- except Exception, e:
- logging.warning('Uninstall failed (%s), still trying ' \
- 'to install newer bundle', e)
- else:
- logging.warning('Unable to uninstall system activity, ' \
- 'installing upgraded version in user activities')
-
- self.install()
-