Mozilla Prism Update
May 21, 2008 – 8:53 pmWe’ve been hard at work on Prism since the 0.9 release in March, and there is a bunch of fancy new features nearing completion. Once we’ve finished testing and tweaking the code, I’ll make some preliminary builds available for folks to hammer on.
Here’s a run down of what’s new, with plenty of gory implementation details for those who are interested in that type of thing.
OS X Improvements
As a devoted convert to the Church of Mac, I’ve tried to get Prism running as well as possible on OS X. Prism 0.9 creates bare bones app bundles on OS X that define some of the basic properties of the app (mainly just Info.plist and icons) but spawn the main Prism bundle in order to execute the application. This has some unfortunately side effects. In particular, the name of the app is displayed as “Prism” in the application menu, and depending on the circumstances the Prism icon may be displayed in the dock instead of the app’s icon. The resulting impression is of an application tacked on top of Prism, rather than the illusion we are trying to create of a true desktop app.
To fix this, I moved much of the Prism code into an extension (prism-runtime@developer.mozilla.org). This can be referenced from each app bundle by including its path in a text file (whose name is the extension’s ID) in the extensions directory of the bundle. (I’m sure this trick must be documented somewhere.) The script to run the app looks like this:
export GRE_HOME="/Users/matthewgertner/Development/prismbase/prism/dist/PrismDebug.app/ Contents/Frameworks/XUL.framework" exec "`dirname "$0"`/prism" -override "/Users/matthewgertner/Library/WebApps/ gmail@prism.app/override.ini" -webapp gmail@prism.app
As you can see, the XULRunner runtime itself is referenced from the main Prism bundle as well, using the GRE_HOME environment variable. In this way, only the actual Prism executable stub (which is tiny) needs to be copied into each app bundle. The result is a much more polished integration of Prism apps into OS X without needless duplication of Prism and XULRunner runtime files.
Splashscreen
Big Ajaxy web apps can take a while to load, and it’s disconcerting to stare at an empty white window while you’re waiting. In the case of Prism, just the basic parsing of initialization data and requesting the app’s main page can cause a perceptible lag, especially on slower computers. To fix this, I implemented basic support for a sort of web splashscreen. To use it, just place a line like this in your webapp.ini:
splashscreen=myfile.html
This is implemented by running a small script just after the <browser> tag is parsed in the main Prism XUL page, setting the “src” attribute of the <browser> to the HTML page. (Like so many Mozilla tips and tricks, I found out from Christian Biesinger that scripts are executed by Gecko as they are encountered during parsing, not once the entire page has been parsed.) The result is near instantaneous display of the “splashscreen”, which is replaced by the actual web app’s page once it has loaded.
Platform API
One of the main goals of Prism is to experiment with ways to improve the user experience of web apps. To achieve this, web apps need to provide additional information beyond their standard user interfaces (generally delivered to the client as HTML, JavaScript and often Flash). Broadly speaking, there are two options in designing APIs for web apps to access Prism functionality:
- Markup: new tags can provide additional data that Prism (and future versions of Firefox and other browsers) can use to enhance the app’s UI. For example, a mail application might include markup (perhaps a microformat or microsummary) specifying how many unread messages are in the user’s inbox. This data might be displayed as a dock badge (by Prism on OS X), as a tray icon tooltip (by Prism on Windows), as some sort of badge in a browser tab (in Firefox) and in a myriad of other ways we have only begun to explore. The markup-based approach is descriptive (as opposed to procedural), and as such is consistent with the general philosophy of the web. There is also a host of application-oriented markup that we can leverage so we don’t end up reinventing the wheel.
- JavaScript API: despite the appeal of a descriptive, markup-based approach, there are advantages to providing a JavaScript API as well. This gives the web app developer more control over how their application interacts with the new features. It can also be more efficient since watching for changes in a site’s markup can be expensive.
The right solution is probably to provide both kinds of APIs, possibly using the JavaScript API as the underlying implementation for the markup-based API. For the time being, we’ve been concentrating on designing and implementing a clean, simple platform API.
The platform API is implemented as a JavaScript global property, a bit of magic that makes a specific component accessible from every window object in a JavaScript application. (Alex Vincent has a good write-up of the general principles involved, although I would recommend using our code as an example since it uses some more modern constructs like XPCOMUtils.) The main interface implemented by our global property is nsIPlatformGlue. I’ll describe specific features in subsequent sections.
Note that the platform API is very much in flux. Some of the newer features (like protocol handler registration) haven’t even landed yet. We’re hoping to get as much feedback as possible about the idea of a platform API in general, as well as the specific way the current API has been designed. It is bound to change in strange and unpredictable ways, so exercise appropriate caution when using it.
System Tray Icon and Minimize/Close to Tray
A tray icon can be displayed on Windows by adding the following line to your webapp.ini:
trayicon=true
The icon can also be shown and hidden programmatically using the platform API:
window.platform.icon().show(); window.platform.icon().hide();
(It would be nicer if “icon” were a property rather than a method, but this won’t be possible until bug 304048 is fixed.)
You can also change the title of the icon (used for the tooltip) by setting it’s “title” property. The “behavior” property can be used if you want your app to minimize and/or close to the system tray:
window.platform.icon().behavior = Ci.nsIApplicationIcon.HIDE_ON_MINIMIZE | Ci.nsIApplicationIcon.HIDE_ON_CLOSE;
Minimize to tray means that the application window is hidden when it is minimized. It can be restored by clicking on the tray icon. Close to tray means that the same thing happens when the X in the app’s title bar is clicked (i.e. it is hidden but keeps running). To close the app completely, choose Exit in the system menu.
The implementation contains vestiges of Mook’s MinimizeToTray extension, as well as some of my own work on generic tray icon support for XULRunner apps. Interest in this type of support remains high, so hopefully the code in Prism will eventually find its way in some form into XULRunner proper.
Dock and Tray Icon Menus
One of the biggest advantages of integrating a web app more tightly with the desktop is the possibility of providing new and potentially more ergonomic ways of interacting with the app. Dock and tray icon menus are an example of this. On the urging of Mike Shaver, Prism uses menu markup from HTML5. This sounds fancy but is actually boringly simple. Just add <command> tags to the <head> of your webpage with “id” and “label” attributes. A DOMActivate event is sent to the tag when the menu item is selected. If you can’t or don’t want to change the web app directly, you can insert <command> tags using DOM methods in the load() handler of your webapp.js file (an optional file located next to webapp.ini in the app’s home directory).
Items are added to the dock/tray menu like so:
window.platform.icon().menu.addMenuItem("myMenuItemItem");
Dock Badges
You can add a badge to the dock icon on OS X (e.g. to display the number of unread messages in a mail app) like this:
window.platform.icon().badgeText = "12";
The implementation is currently based on ancient code from Thunderbird, but I am planning to port it to more modern APIs and provide some more flexibility in formatting the badge (fonts, colors, placement, etc.).
Protocol Handlers
A key aspect of desktop integration is the ability to use a web app as the default handler for a specific type of URL. Taking again the example of a mail app, I might want Gmail or whatever webmail I use to open in Prism when I click on a URL with the mailto: scheme. This can be accomplished using Prism’s protocol handler support:
window.platform.registerProtocolHandler("mailto", "http://mymailapp.com/compose?to=%s");
This installs the protocol handler in the system registry (or Launch Services database on OS X), so the Prism app is automatically started when the URL is clicked. If it is already running, the existing instance is used to open the appropriate page.
This approach is a bit problematic for large Ajaxy apps like Gmail, since gobs of JavaScript have to be reloaded when a protocol handler is invoked. We are therefore planning a second API that will let the app specify a JavaScript callback to be used if the app is currently running.
For an example of how a sophisticated webapp.js can use some of these features, see the great script that Steve Krulewitz has written for Gmail (a work in progress but one that I already find indispensable for use with my own prismified Gmail app). I’m planning to extend the script to support dock badges and protocol handlers, if Steve doesn’t beat me to it.
A much-discussed point has been how these new features and APIs can be used in Firefox as well as Prism. Please don’t take any of the above as set in stone. I hope that by posting this we can get some constructive feedback about what’s good, bad and ugly about the way our API is designed. Note also that most of the above-mentioned features are implemented only on Windows and OS X at present. I am planning to port them to Linux when I have time, but naturally contributions would be most welcome.
30 Responses to “Mozilla Prism Update”
where’s the Tiger version
By turha on May 22, 2008
Everything I mentioned above works fine on OS X Tiger.
By Matthew Gertner on May 22, 2008
So can the main web app file be a local file in the app bundle, rather than a URL? (You know where I’m going with this)
And can we also point to a XUL file as the main app file, possibly with chrome privileges?
If at least one of the two above were possible it would make Prism a lot more interesting, to me at least.
By enefekt on May 22, 2008
I guess you want to use Prism for a local app? Right now people are doing this with a local web server, but I think the new offline capabilities could be a better solution in the long term. I suppose you could just point to a file: URL if all the links resolved properly to other local files.
Not sure about using XUL as the app file. Why not just use XULRunner in that case?
By Matthew Gertner on May 23, 2008
I was wondering if Prism provides (or could provide) any kind of Zeroconf support. The idea behind this is to remove most of the steps to setup a LAN application. I start somewhere on my LAN an HTTP server providing, let say, an online accounting app, and the users just need to launch a Prism-based interface on their desktop to automatically get connected to the app. From anywhere. Of course, there’s some pending security issues (Zeroconf spoofing for instance), but, in a closed environment it could be interesting.
By Skadge on May 23, 2008
No Zeroconf at present unless there’s something built into Mozilla itself that I don’t know about (doubtful). But it’s a neat idea, thanks for the suggestion.
By Matthew Gertner on May 23, 2008
“Why not just use XULRunner in that case?”
The whole rolling-your-own aspect, not to mention if Prism will be better integrated with Firefox 3, you don’t automatically get that with XULRunner right?
By enefekt on May 23, 2008
Well the integration with Firefox is based on the idea that you will be spinning of a normal HTML+JS-based web app. Still not sure I understand entirely what you’re trying to achieve. Maybe a concrete example might help?
By Matthew Gertner on May 23, 2008
>can we also point to a XUL file as the main app file
Yes. I’ve been using a xul file for a long time:
http://s3.amazonaws.com/xdexavier/multirunner.xul
Go to the Configuration/About tab for more info.
By xavier on Jun 18, 2008
How can you add sub-menus and menu separators to “Dock and Tray Icon Menus” of prism? Is it even possible? Thanks.
By Jay on Jul 30, 2008
There is no support for submenus right now but it would be straightforward to implement. Can you file a bug so we get this on our radar?
By Matthew Gertner on Jul 30, 2008
Thanks for the update. I’m a bit confused right now. Can you tell me how an webapp.js has exactly to look like when wanting to implement a “minimize-to-tray” functionality?
I put a single-line webapp.js with
window.platform.icon().behavior = Ci.nsIApplicationIcon.HIDE_ON_MINIMIZE
but that (obviously) didn’t work.
Any help is greatly appreciated!
By Herve on Aug 5, 2008
Herve,
If you set the trayicon item in webapp.ini to true, hide on minimize should be turned on by default.
In any case, I think your example isn’t working because you want something like:
function load()
{
window.platform.icon().behavior = Ci.nsIApplicationIcon.HIDE_ON_MINIMIZE;
}
If you don’t put your code in one of the callbacks used by prism (startup, load, etc.) it will never be called.
By Matthew Gertner on Aug 5, 2008
Thanks for your reply.
I set trayicon=true and put the code you mentioned in the webapp.js, zipped everything and installed it.
I do get an icon in the tray and I can minimize the app, however it will not “disappear” from the task bar. I would like to *only* have an icon in the tray and not in the taskbar.
(so not just “minimize and display also in tray” but “minimize to tray”)
Best,
Herve
By Herve on Aug 6, 2008
Can you rig it up so that the splashscreen HTML document may survive being zipped to a webapp bundle? You will need to mess with the list of allowed file names, so maybe if it had a fixed name?
By Wired Earp on Aug 18, 2008
Wired,
We’re doing bug triage for Prism 1.0, so now is the perfect time to file your request in Bugzilla if you want us to consider it.
By Matthew Gertner on Aug 19, 2008
I am interested in the same thing as “enefekt”
I already have my application running on xulrunner 1.9 distribution, all the application files are local.
I want to be able to minimize the application to tray so i was wandering if somehow i can use your runtime (xulrunner dir + maybe extensions,components) to have that feature since the the default xulrunner does not provide that.
Thank you
By Tristan on Sep 25, 2008
Tristan,
Someone would have to port the tray code to XULRunner. This wouldn’t be too difficult a task. I’m hoping someone will volunteer at some point to do this.
By Matthew Gertner on Sep 26, 2008
I can’t get any of the webapp.js files to work on Prism 0.9. (Even in the bundles on the mozilla site)
They all error out!
The error console fault’s at any native javascript functions. “setInterval is not defined”, “alert is not defines”, “host is not defined”.
Worked fine on 0.8 but I really wanted that system tray functionality.
Sorry I’m posting here, but the mozilla labs forum hasn’t been working either! Really frustrating.
By adam on Nov 24, 2008
Have you tried Prism 0.9.1?
By Matthew Gertner on Nov 27, 2008
Hi,
‘window.platform.registerProtocolHandler(”mailto”, “http://mymailapp.com/compose?to=%s”);’ doesn’t work.
To get it working you have to write: ‘window.platform.registerProtocolHandler(”mailto”, “http://mymailapp.com/compose?to=%s”, null);’
This was at least what I had to do…
By ClouDtheStrifE on Mar 2, 2009
That’s true in 0.9.1 but I’ve changed it for 1.0. I’ll be posting new docs.
By Matthew Gertner on Mar 2, 2009
I’m really looking forward to 1.0! Can you state an approximately date? I would be delighted to get any information!:)
By ClouDtheStrifE on Mar 3, 2009
I’m not going to go out of a limb and name a date, but we’re finishing up the last few bugs so should be soon.
By Matthew Gertner on Mar 4, 2009
Хм,несогласен с предыдущими ораторами
Споки Bye
By Gostixel on May 16, 2009
Hue hue, i had tested it one year ago or more i don’t remember, and too buggy.
I retested that yesterday : impossible to open the app from the tray icon (just close and minimize to).
When attaching to the taskbar, the icon disappear for the generic (exe) icon.
When creating another instance with the same url than an existing one, both merges..
Really, how many guys are working on the project ? What’s doing Mozilla with “projects” that don’t finish to be projects ?
Really disappointed again as it can be so useful and a real need.
Continue your efforts, but Mozilla, what’s the real purpose of a lab that don’t have the force (money) to produce ? Seems that it’s just for demonstration !
By frenchdevelopper on Jun 12, 2009