Creating a XULRunner 1.9 App on OS X

I’ve just created my first simple XULRunner-based application.  In order to make creating the application work in OS X, a number of different steps have to be taken from the Windows version.  Unfortunately, there doesn’t seem to be a comprehensive guide for newbies to do so, so I created my own based on several resources.  Since much of what follows is direct quotes or slightly modified, I want to be sure to give credit where credit is due:

http://developer.mozilla.org/en/docs/Getting_started_with_XULRunner
http://groups.google.pt/group/mozilla.dev.tech.xul/browse_thread/thread/d8c0127036615492
http://rcrowley.org/2007/07/17/cross-platform-xpcom-a-howto/
http://developer.mozilla.org/en/docs/XULRunner:Deploying_XULRunner_1.8

Step 1: Install the XULRunner Framework

The first step is to download and install the XULRunner Framework.  XULRunner may be downloaded from here: http://developer.mozilla.org/en/docs/XULRunner.  On the Mac, just run the installer, which installs XULRunner as XUL.Framework in the /Library/Frameworks directory.

Step 2: Set up the Application Directory Structure

I created the root in a new /Users/{username}/Desktop/approotfolder folder, but you can create it wherever you like. Here is the subfolder structure:

../approotfolder
…./myapp
……/chrome
……../content
……….main.xul
……chrome.manifest
…./defaults
……/preferences
……..prefs.js
….application.ini

Notice that there are 4 files in the folder structure: application.ini, chrome.manifest, prefs.js, and main.xul.

Step 3: Set up the XUL Application Files

Application.ini

The application.ini file acts as the XULRunner entry point for your application. It specifies how your application intends to use the XULRunner platform as well as configure some information that XULRunner uses to run your application. Here is mine:

[App]
Vendor=Finkle
Name=Test App
Version=1.0
BuildID=20060101
Copyright=Copyright (c) 2006 Mark Finkle
ID=xulapp@starkravingfinkle.org

[Gecko]
MinVersion=1.8
MaxVersion=1.9.0.*

chrome.manifest

The chrome manifest file is used by XULRunner to define specific URIs which in turn are used to locate application resources. This will become clearer when we see how the “chrome://” URI is used. Application chrome can be in a single or a few JAR files or uncompressed as folders and files. I am using the uncompressed method for now. Here is my manifest:

content myapp file:content/

prefs.js

The prefs.js file tells XULRunner the name of the XUL file to use as the main window. Here is mine:
pref(”toolkit.defaultChromeURI”, “chrome://myapp/content/main.xul”);

XULRunner preferences include:
toolkit.defaultChromeURI
Specifies the default window to open when the application is launched.
toolkit.defaultChromeFeatures
Specifies the features passed to window.open() when the main application window is opened.
toolkit.singletonWindowType
Allows configuring the application to allow only one instance at a time.

This is described in further detail in XULRunner:Specifying Startup Chrome Window.

main.xul

Finally, we need to create a simple XUL window, which is described in the file main.xul. Nothing fancy here, just the minimum we need to make a window. No menus or anything:

<?xml version=”1.0″?>
<?xml-stylesheet href=”chrome://global/skin/” type=”text/css”?>

<window id=”main” title=”My App” width=”300″ height=”300″
xmlns=”http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul”>
<caption label=”Hello World”/>
</window>

Note: Make sure there is no extra whitespace at the beginning of the XML/XUL file

Step 4: Set up the OS X .app directory structure.

XULRunner for Mac is slightly more complicated because of strict requirements for GUI apps running in OS X. First, go download XULRunner and install the package. It will create itself deep within /Library/Frameworks (quite separate from the Windows version). In myapp, create a new directory called MacApp.app or something else ending in .app. Within this directory create one called Contents (capitalization is important), and within Contents create Frameworks and MacOS. Now create three symbolic links to complete the Mac directory structure:

ln -s /Library/Frameworks/XUL.framework MacApp.app/Contents/Frameworks/XUL.framework
ln -s ../../../myapp MacApp.app/Contents/MacOS/Resources
ln -s /Library/Frameworks/XUL.framework/Versions/Current/xulrunner MacApp.app/Contents/MacOS/xulrunner

If you would like to ship the application on a private install of XULRunner, you could always just copy the respective files into the XUL.framework and the MacOS/xulrunner directories.

Now create MacApp.app/Contents/Info.plist and dump this in, making sure to change things in ALL CAPS. I am almost certain this is not optimal as it repeats itself a lot. But it is functional.  Note: when using XULRunner 1.9, it doesn’t seem to matter what is in this file, or even that it exists.  XULRunner generates its own Info.plist file.

<?xml version=”1.0″ encoding=”UTF-8″?>
<!DOCTYPE plist PUBLIC “-//Apple Computer//DTD PLIST 1.0//EN” “http://www.apple.com/DTDs/PropertyList-1.0.dtd”>
<plist version=”1.0″>
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleExecutable</key>
<string>xulrunner</string>
<key>CFBundleGetInfoString</key>
<string>3.0</string>
<key>CFBundleIdentifier</key>
<string>YOUR_APP_ID</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>YOUR_APP_VERSION</string>
<key>CFBundleName</key>
<string>YOUR_APP_NAME</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>YOUR_APP_VERSION</string>
<key>CFBundleSignature</key>
<string>YOUR_APP_ID</string>
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleURLName</key>
<string>YOUR_APP_NAME</string>
<key>CFBundleURLSchemes</key>
<array>
<string>chrome</string>
</array>
</dict>
</array>
<key>CFBundleVersion</key>
<string>YOUR_APP_VERSION</string>
</dict>
</plist>

Review Directory Structure:

As a review, here’s how our tree looks now:
/approotfolder
.. /myapp
…. /chrome
…. /content
…… main.xul
…. chrome.manifest
…. /defaults
…… /preferences
…….. prefs.js
…. application.ini
.. /MacApp.app
…. /Contents
…. /Frameworks
…… XUL.framework→/Library/Frameworks/XUL.framework
…. Info.plist
…. /MacOS
…… /xulrunner→/Library/Frameworks/XUL.framework/Versions/Current/xulrunner
…… /Resources→../../../myapp

Step 5: Run the Application

The moment of truth. We need to get XULRunner to launch the bare-bones application.  Before you can run a XULRunner application, you must install it using the –install-app xulrunner commandline flag. Installing the application creates an OS X application bundle:

/Library/Frameworks/XUL.framework/xulrunner-bin –install-app /<path>/<to>/myapp.zip

Once installed, you can run the application:

/Library/Frameworks/XUL.framework/xulrunner-bin “/Applications/Finkle/Test App.app/Contents/Resources/application.ini”

You should now see a window that looks something like this:

This application will output to Applications/Vendor Name/App Name (as specified in the application.ini).

Since XULRunner 1.9 seems to generate its own plist file (disregarding anything in the custom one), I’m not sure how to add application icons yet.  I’m sure there’s a way to specify this in the application.ini somehow, but since I’m brand new to XUL/XULRunner I can’t really speak to that.

Leave a Reply

You must be logged in to post a comment.