FlashBridge: proxying Flash <-> OpenLaszlo

Posted by Oliver on April 13, 2008

I’ve updated my OpenLaszlo utility grab-bag to make browser <-> applet communication even easier. How easy?

Proxies

Put this in your browser JavaScript:

var gObject = {
  f: function() { console.info('gObject.f', arguments) },
  g: function() { console.info('gObject.g', arguments) }
};

And this in an OpenLaszlo applet:

var gObject = FlashBridge.createRemoteProxy('gObject', ['f', 'g']);
gObject.f(1, 2);
gObject.g(3);

When you run the applet code, it prints this to the browser console:

gObject.f [1,2]
gObject.g [3]

That’s right, Flash is invoking the function calls, but they’re executing in the browser.

Now switch these around — put the first block in the applet, and the second block in the browser JavaScript — and it still runs the same way, except that it’s the browser that invokes the functions, and they run in the applet (and print to the OpenLaszlo debug console, if the applet was compiled with debugging on).

(By the way, the full sources for the examples are here.)

Return Values

Callbacks, or continuations for return values, make it easy for the applet to operate on the return value from a call into the browser, even though these calls are asynchronous.

Put this in the browser:

var gService = {
  add: function(a, b) {
    logCall('gBrowserObject.add', arguments);
    return a+b;
  },
  error: function(msg) {
    logCall('gBrowserObject.error', arguments);
    throw msg;
  }
};

And this in the applet:

gBrowserObject.add(1, 2).onreturn(function(value) {
  console.info('1 + 2 -> ' + value);
});
gBrowserObject.error('error msg').onexception(function(value) {
  console.info('error !> ' + value);
});

The argument to onreturn is called (asynchronously) with the return value. The argument to onexception is called with the message from the exception, if an exception occurred.

Callbacks, unlike proxies, only work one direction — for calls from the applet to the browser. That’s not for a technical reason — I’ve just only needed it one direction so far.

Call Storage

Browser code can call into the applet even if the applet hasn’t initialized yet, and vice versa.

To implement this, each side of the bridge stores calls (and return value handlers) in a mailbox until it hears back that the other side has loaded. Once this happens, the mailboxes are flushed and the remote call methods switch to direct invocation.

This works around a couple of race conditions. First, the applet won’t generally have run its initialization code by the time the browser receives its load event, so a naive implementation of the bridge wouldn’t allow the browser to make calls into the applet until the browser had heard back that the applet had loaded — which is hard to detect. (It isn’t enough to wait for the object’s onload event, because this can trigger before the first frame of the movie plays, so the applet may still not have initialized enough to receive messages.) Conversely, depending on your page organization and initialization raindance, the applet might load before page side has registered — so the applet couldn’t call into the page until an unknown time.

Security Implications

FlashBridge, by default, allows the browser to call anything sitting in the applet, and vice versa. This increases the attack surface of your application, because it allows an embedded Flash applet to invoke any part of it. This means that an XSS can tunnel through your applet to gain access to any site with a crossdomain.xml file that allows your applet to connect to it — something that XSS on a pure JavaScript page can’t do.

It you prefer not to audit your application against this, you can call FlashBridge.secure to prevent it from accepting arbitrary calls, and then FlashBridge.register to register callins.

There’s no lockdown facility in the other direction — to lock down the browser JavaScript against calls from the Flash application. That’s because it’s trivial for a Flash application to invoke arbitrary JavaScript in the browser context — in fact, that’s how the applet -> browser communication is implemented, and if that were secured at the FlashBridge layer, the vulnerability would still be accessible one layer down.

Gitting It

All this is in the LzOsUtils project on GitHub, with examples here. Download it via the Download button, clone it via git clone git://github.com/osteele/lzosutils.git, or add it as a submodule to an existing git repo via git add submodule git://github.com/osteele/lzosutils.git.

FlashBridge is written for OpenLaszlo, but would probably run in straight Flash too. And it uses my own funky alternative to ExternalInterface for calling from Flash to the browser (since the built-in API is seriously broken), but it could be ported to run on top of Dojo or something pretty easily.

What I didn’t get to 5

Posted by Oliver on December 31, 2007

Here are some of the weekend projects that I didn’t finish this year. These aren’t good enough to put on my project list or my sources page. Some of these aren’t even working, and some of them I might not finish at all (most of my weekends are spoken for). And some of them I can’t bear to look at (I’m not proud of the code, and don’t want to be judged by it…), but I’m making myself put them out there anyway. I feel bad for the neglected little things, trapped on my hard drive, and I’d like to let them see the sun, even if just briefly before they flicker out and die.

Libraries:
* LzOSUtils — jQuery-compatible ajax function, Flash->JS bridge with callbacks, declarative Flash 8 filter effects, console that reports to Firebug, dashed lines, Prototype-compatible string and collection methods, etc. Completely undocumented and fairly disorganized.
* LzTestKit — mocks and asynchronous and automated testing for OpenLaszlo; still pretty raw.
* HopKit — a “higher order programming kit”, for constructed chained APIs such as in LzTestKit’s mocks and expectations; still somewhat buggy and undocumented.
* MVars — a port of Haskell MVar’s to JavaScript. I realized that what I actually needed for real-world applications was an implementation of the join calculus (a la JoCaml). I haven’t written the join calculus version.
* Protodoc — I wrote this to extract the docs from the source files and to implement the live examples in Functional and Sequentially; it includes a version of the wonderful doctest, for JavaScript. I got part way through refactoring it into something that isn’t quite put together again. I haven’t decided whether to finish it or whether there’s an existing project that’s close enough.
* [No link yet] Updates to OpenLaszlo JSON and ropenlaszlo, from using them over the past year. (No, those links go to the old versions — I haven’t uploaded the updates :-(
* Implementations in Ruby and JavaScript of the awesome CFDG. I wrote these a couple of years ago, and really want to update and clean them up to point where I can donate them to Hackety Hack, or someone else who might use them.

Applets:
* TilesHTML port of my mid-nineties Java version (which was a port of my mid-eighties C version), uses the Canvas tag; probably doesn’t work in MSIE
* IFS — a few minutes of pair programming with my son to show him some stuff about matrices; probably doesn’t work in MSIE
* On this day — iPhone applet; the feed is down right now
* Force-directed layout for my home page — this was my experiment using HTML instead of Flash; I got discouraged when I saw how bad the frame rate for full-page animation is was even in Firefox, let alone MSIE (Safari rocks now, though!)

Plus a couple dozen essays that are half or three-quarters written (programming, software development, math education), a couple of AJAX presentations, and two workbooks for teaching abstract math at the elementary level. It takes me longer to write an essay than a program, though!

More weekends, please.

Canvas with Text 1

Posted by Oliver on February 27, 2006

The two times that I’ve used the WHATWG canvas element recently, I’ve wanted a canvas with string rendering. The most recent time that I’ve used the OpenLaszlo drawview class (which has substantially the same API), I’ve wanted string rendering too.

The graph in reAnimator is a drawview, but with text labels for the edges. And the graph and parse tree in the Graph and Parse tabs of reMatch both use WHATWG canvas for lines, but text for labels. (These tabs are only visible in Firefox, for now.)

TextCanvas.js implements the canvas context extended with labels, for DHTML. And “textdrawview.lzx” implements drawview extended with labels. They share the same API, so that I can write graphics libraries (such as graph drawing) that work with both DHTML and OpenLaszlo. That API is described here.

The first example below is an OpenLaszlo application that uses textdrawview; view source here.

If you’re using Firefox, you can also view the DHTML example. This uses TextCanvas; open it in a separate page here.

Files:
* textcanvas.jsDHTML implementation
* textcanvas-example.htmlDHTML example (shown running above)
* textdrawview.lzx — OpenLaszlo implementation
* textdrawview-example.lzx — OpenLaszlo example (shown running above)
* textcanvas-apiAPI documentation

Some example code:

// <div id="canvasContainer"></div>
var container = document.getElementById('canvasContainer');
var textCanvasController = new TextCanvasController(container);
var ctx = textCanvasController.getContext('2d');
ctx.moveTo(0, 0);
ctx.lineTo(100, 100);
ctx.stringStyle.color = 'red';
ctx.drawString(0, 0, "red");
ctx.stringStyle.color = 'blue';
ctx.drawString(100, 100, "blue");

Javascript Beziers 7

Posted by Oliver on February 26, 2006

The OpenLaszlo application below demonstrates animation along a line, a quadratic Bezier, and a cubic Bezier (the top three paths). It also demonstrates (the bottom path) animation along a path composed of multiple segments.

Drag the slider back and forth to display the point on each path at t=slider.value/100, or click the “Animate” button to animate t from 0 to 1.

I wrote this in order to animate the state markers along the edges of the graph in reAnimator. The GraphViz dot tool, which I’m using for graph layout, generates cubic beziers, so I had to write code to render and evaluate them.

If you’re writing for FireFox a Browser that supports the canvas element, you can use the same code with the new HTML canvas element. Click on “Start Animation” to animate the points on the canvas below. And click here to open the HTML applet in its own window.

Files:
* bezier.js — measurement, interpolation, sampling, and subdivision for arbitrary-order Beziers
* path.js — measurement, interpolation, and sampling for paths composed of multiple lines and Beziers
* bezier-demo.js — the code to draw the paths in the demo. This is platform-agnostic, and works in OpenLaszlo (bezier-demo.lzx) and HTML (bezier-demo.html).
* bezier-demo.lzx — the OpenLaszlo demo
* bezier-demo.html — the HTML demo
* drawview-patches.js — patches to the OpenLaszlo LzDrawView. This includes an implementation of LzDrawView.bezierCurveTo.

A couple of caveats:
* This animates along the Bezier parameterization, not the path length. This was good enough for my application, but you could get animation that speeds up and slows down, depending on how you choose your control points.
* The demo code is written for brevity, not speed. In particular, it re-renders the background each time, which involves some expensive math to render the cubic. In reAnimator, I placed the animated elements on a separate view in front of the background. I didn’t do that here because I wanted to share code between the OpenLaszlo and HTML demos, and the techniques for doing overlays were too different.Using a separate overlay for the background didn’t actually speed this up. The hot spot is the parametric position calculation.

1 I think the reason the code doesn’t work in Safari is that Bezier.draw uses the Function.apply method to apply methods on the graphics context, such as quadraticCurveTo, to argument lists. It looks like Safari doesn’t implement apply when the function is a native method. I didn’t try to work around this because in cases where I’ve actually tried to use canvas (such as the “Parse” and “Graph” tab in reWork), there were other problems with Safari anyway.

Update: The inline examples weren’t showing up. Thanks to Bret Victor for both finding and diagnosing the problem. (I was linking to my laptop, osteele.dev. The post looked fine from my laptop!)

JSON for OpenLaszlo 8

Posted by Oliver on February 20, 2006

JSON for OpenLaszlo is a JSON library for OpenLaszlo.

I wrote this in order to implement my regular expression visualizer.

There’s a live example below. Clicking on a button requests some JSON text from the server and parses it on the client. The source code to the example is here.

(When it runs off my web site, the debugger in the example displays a warning about not being able to connect to the LPS server. This means that the debugger can’t evaluate expressions, as it could if you were running it off the SDK. I’m just using the debugger here to print inspectable representations of the JSON parse results, and the warning doesn’t affect this.)

Rationale

OpenLaszlo implements most of JavaScript 1.5 (ECMAScript 3), but it’s missing regular expressions and throw/catch, so it can’t run JSON in JavaScript. And the OpenLaszlo compiler doesn’t (yet) implement the proposed JavaScript 2.0 (ECMAScript 4) extensions such as class and type declarations, so JSON in ActionScript doesn’t work either. Hence, this implementation, which doesn’t require either regular expressions or JavaScript 2.0 extensions.

It’s open source, of course. (MIT License.)

Visualizing Regular Expressions 38

Posted by Oliver on February 19, 2006

Here’s something I’ve wanted for a long time. So I finally built it. reAnimator is a tool for visualizing how regular expression engines use finite-state automata to match regular regular expression patterns against text.

This is intended to demonstrate the implementation of regular expressions. If you want to learn how to use them instead, I recommend these references instead:
* Regular-Expressions.info
* A.M. Kuchling’s Regular Expression HOWTO
* Steve Mansour A Tao of Regular Expressions
* Jeffrey Friedl’s Mastering Regular Expressions
* The Regular Expression Library’s list of resources
* New My own reWork online regular expression workbench.

The User Interface

The screen has these areas:

The Pattern

The “pattern” shows the regular expression. Click on it to set another regular expression to match against.

The Input

The “input” is the string that is matched. As you type into the input string, the color of this string indicates whether it’s a complete match (green), a partial match (blue), or a non-match (red).

The Graphs

There are two graphs, which each display a finite-state automaton (FSA) that corresponds to the regular expression in the “pattern” area. As you type into the “input” area, the graphs also update, to display the state of the match.

A deterministic FSA (a DFA) is like a board game, with a counter that is moved according to the successive letters of the input string. The counter starts at the initial state (the leftmost circle with the arrow from off the board). Each consecutive letter of the input string tells where to move the counter to next. If the counter ends up in a terminal state (a double circle), there was a match.

A nondeterministic FSA is the same except that when there’s more than one legal move, you take them both.

The nondeterministic FSA bears the most direct resemblance to the regular expression. In exchange for this simplicity in its construction, it’s more complex to evaluate: instead of keeping track of just one counter, you have to keep track of a set of them. (This is an instance of the compile-time versus execution-time trade-offs that computer science is rife with.)

If you want to learn more about finite-state automata, the wikipedia entry has some useful information, but this also seems like a good place to plug my father-in-law’s book.

Implementation details

The front end is written in OpenLaszlo, and compiled to Flash. It uses AJAX and JSON to request the FSAs and the graphs.

The back end is written in Python and C. The Python part is my PyFSA library, plus a bit of glue to turn various JavaScript objects and graph files into JSON strings. There’s also a cache so that my shared server doesn’t get quite so stressed even if the site becomes popular. (Having the front end logic on the client should help here too.)

The C portion is the wonderful GraphViz. PyFSA creates a .dot file for each FSA, and uses GraphViz to lay out the graph. The server parses the annotated .dot file into a JavaScript object, and uses JSON to download the resulting graph to the client.

An OpenLaszlo class on the client interprets the JavaScript graph description into a sequence of drawing instructions. It also saves the node positions, so that it can animate against them.

Update: Some of the support libraries are now available as open source. See JSON for OpenLaszlo, JavaScript Beziers, and Canvas with Text. OpenLaszlo and PyFSA were available previously.

Implementation choices

Client vs. server: There’s no reason that this couldn’t be a client-side-only application. I just happened to have PyFSA lying around, and didn’t feel like porting it to JavaScript. My goal for this was one day of implementation time, and I didn’t think porting PyFSA would fit into this. (It ended up taking three days anyway, because I forgot about implementing cubic beziers and JSON, and because I got carried away and added animation.)

CGI vs. FastCGI: I’ve been doing most of my server-side programming with either PHP or FastCGI and Ruby, so that pages don’t take so long to serve. This is the first Python service I’ve deployed since I started using FastCGI, and I was planning to use it. But Python doesn’t include FastCGI in its library, and the fact that there were four different third-party libraries with different APIs, none of them endorsed, and that the latest PEP to mention FastCGI was deferred five years ago, made me unwilling to take on the project of evaluating them.I’m glad to hear that I was completely off base about Python and FastCGI. See Phillip J. Eby’s comment below. I stuck with CGI, which is in the standard library.

OpenLaszlo vs. DHTML: It would be just as easy to draw the graph itself using the canvas class in DHTML. I balked at doing the animation and user interface in DHTML, though. (There’s little touches like laying the graphs out horizontally only if there’s enough room, which were only a few lines of declarative code in OpenLaszlo.) And then it wouldn’t have worked on as many browsers. I decided to wait until OpenLaszlo compiles to DHTML, for a DHTML version of this.

PyFSA vs. …: Higher-performance © implementations of FSA minimization and determinization exist. I went with my own because it’s the only one I know of that has the option of preserving source location information across transformations. I use source location information minimally in the interface, and might add more.

Credits

Thanks to Margaret Minsky and Gary Drescher for commenting on a draft of the application. I used Patrick Logan’s json-py for server-side JSON. The credits for GraphViz are here. Thanks to my former colleages at Laszlo Systems, Inc. for helping create the OpenLaszlo platform. I adapted Philip J. Scheider’s code for subdividing cubic beziers; this is a compact implementation of de Casteljau’s algorithm for Algol-like languages. Thanks to Guido and company for Python. Lastly, since people always ask, I drew the architecture diagram with Omigraffle (gee I wish I got a commission!) — which I like because I’m not much of a designer, and diagrams I draw with it are passable without much work.

Update: I changed the name to reAnimator. (It was reMatch.) Thanks to Apache RewriteRule for letting me do this without breaking the old URLs!

Visualizing Subversion Project Activity 3

Posted by Oliver on January 31, 2006

Last week I wrote a couple of tools to keep track of subversion checkins:

The Subversion Log Viewer is a master-detail list of recent subversion revisions. It’s based on the OpenLaszlo contactlist example. The nicest feature is really an afterthought: at the last moment, I added faces for authors; I think this makes projects a lot friendlier. Right now it only adds the faces to the OpenLaszlo log; let me know if you’re interested in using this for your own project, and I’ll make a public API for adding faces to a repository.

The Subversion iCalendar Gateway transcodes subversion logs into iCalendar files, that you can subscribe to with Apple iCal or Mozilla Sunbird. I find it useful for a projects that I want to check in on occasionally. Unlike an RSS feed, it gives you a sense of the activity level and the change frequency, at least if you’re a spatial person like me.

Both of these point at the OpenLaszlo log by default, but they’ve got a UI for putting in any subversion repository (http: or svn: protocol only), and generating a permalink for that repository.

One caveat: It takes a long time to request a complete subversion log, so the iCalendar gateway only requests the first 500 revisions the first time you (or anyone) view a given calendar, and then the next time anyone or refreshes the same calendar, it catches up to the present 500 revisions at time.

Expialidocio.us 1

Posted by Oliver on January 08, 2006

Expialidocio.us is a tool for visualizing your del.icio.us posting activity. It displays a graph of your posting activity over time. You can select a timespan from this graph, and it will show you a tag cloud weighted by just those dates.

Expialidocio.us was inspired by a posting by Jon Udell. Coming full circle, Udell has posted since posted about this application. Since then, I’ve published the sources.

OpenLaszlo Ruby library

Posted by Oliver on January 05, 2006

openlaszlo.rb is a Ruby library for compiling OpenLaszlo programs. I use it to build this, this, and the toolbar here. This article describes how to use it with Rake.

Update: This is now available as a gem. The rdocs are here.

OpenLaszlo Blog

Posted by Oliver on November 11, 2005

It was months in the conception, weeks in the making, and minutes in the configuration, but the OpenLaszlo project now has a blog.  That blog is intended for project-related news, announcements, documentation, and musings, posted by members of the OpenLaszlo project and some of our co-workers at Laszlo Systems. And I’ll be returning this blog to more personal and broader topics. (Those are two overlapping categories, not one.) Plenty of Laszlo and RIA stuff where it goes beyond the immediate project work, but more other topics too.

On a related topic, Laszlo Systems has launched Laszlo Mail, a high-polish web mail product focused on cross-browser portability and on user experience . I first wrote about Laszlo Mail here. Laszlo Mail is an excellent example of the kind of application that we created OpenLaszlo in order to enable.  As Jonathan Boutelle says :” It feels like a candy-coated swiss army knife, an appealing mix of aesthetics and pragmatic design.”

Congratulations to the Laszlo Mail team on getting this done. The Laszlo Mail team has a blog too, here.