I started working on this library months ago and it’s been getting some use already. I spoke about it a bit at Mozilla Summit and as a result there was a post on Ajaxian, but for the most part I’ve been holding off on promoting it until I solidified the API and pushed out a solid release.
jsbridge is a Python to JavaScript translation interface for Mozilla applications. It’s implemented as an extension and can be dynamically installed and launched in a new “clean” profile using mozrunner.
You can call functions and set variables in any window in any scope from Python and those objects are returned and represented as Python objects (which are just classes that inherit from Python base types). There are obvious limitations for assignment and representations in Python, you can really only send objects over the bridge that can be JSON serialized, but it does support assignments by reference so you can move around and manipulate anything that’s already there.
But the most interesting feature is the event system. The event system is available as a resource from inside the Mozilla environment (in other words you can import it from your Firefox extension). Events fired on the JavaScript end are serialized as JSON and sent to the Python side. This means you can add listeners in Python to events fired from the Mozilla JavaScript environment.
This is a big deal. It means we can write significantly cleaner tools. We can now create tools solely as Firefox extensions that don’t require any special Python code to run, but have code that checks if jsbridge is installed and send pertinent events over the bridge for continuous integration. No more printing to console and parsing in Python, no more outputting to log files and parsing them, no more scripts calling scripts and OH MAN MY HEAD HURTS!
The documentation has some great examples.
For a little snippet of the events system in the wild here is some new mozmill Python code that sends all the events to the Python logger.
import logging logger = logging.getLogger("mozmill") from jsbridge import events class LoggerListener(object): cases = { 'mozmill.pass': lambda obj: logger.debug('Test Pass: '+repr(obj)), 'mozmill.fail': lambda obj: logger.error('Test Failure: '+repr(obj)), } class default(object): def __init__(self, eName): self.eName = eName def __call__(self, obj): logger.info(self.eName+' :: '+repr(obj)) def __call__(self, eName, obj): if self.cases.has_key(eName): self.cases[eName](obj) else: self.cases[eName] = self.default(eName) self.cases[eName](obj) events.add_global_listener(LoggerListener()) logging.basicConfig(level=logging.ERROR)
