Friday, January 29, 2010

Using Firefox profiles on Mac OS X

If you are a Firefox power user, you are probably familiar with its profile system. A profile is a folder where Firefox keeps all your customizations, history, bookmarks, cookies, and other data.

Firefox lets you run several independent instances using different profiles simultaneously -- by specifying special options in the command line. The basics are covered in this lifehacker article.

Unfortunately on Mac OS X there's no easy way to specify command line parameters in a "shortcut", like there is on Windows. The well-known workarounds are:
  1. Use Terminal.app or similar to execute /Applications/Firefox.app/Contents/MacOS/firefox-bin with the necessary parameters.
  2. Use a separate launcher application like MultiFirefox, which is similar to Firefox's own profile manager, and also lets you choose the Firefox version to run.
  3. Use Script Editor.app to create an "application" that runs Firefox with the command-line parameters you want.
  4. Create multiple slightly edited copies of Firefox.app that run with the specified profile.
I used a combination of these until recently, and they're all imperfect: the first and second workarounds require several steps to run Firefox, and the third option was too slow for me. The fourth just seems wrong.

My solution

This solution was tested with Mac OS X Leopard, Snow Leopard, and Lion. We create a lightweight bash-based application, which starts Firefox with the right command line arguments.

You can download a zip with the template application, which should show the profile manager when run (assuming you have Firefox installed to the standard location).

Here's how you create this application:

  1. Create a folder /Applications/FirefoxWork.app with a folder Contents inside it. (To open an *.app folder in Finder use the context menu Show Package Contents.)
  2. Inside the Contents folder create a file named Info.plist (note: all names are case sensitive!) with the following contents:
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
    <plist version="1.0">
    <dict>
      <key>CFBundleExecutable</key>
      <string>FirefoxLauncher</string>
      <key>CFBundleIdentifier</key>
      <string>com.example.FirefoxLauncher</string>
      <key>CFBundleInfoDictionaryVersion</key>
      <string>6.0</string>
      <key>CFBundleName</key>
      <string>FirefoxLauncher</string>
      <key>CFBundlePackageType</key>
      <string>APPL</string>
      <key>CFBundleSignature</key>
      <string>????</string>
      <key>CFBundleVersion</key>
      <string>1.0</string>
    </dict>
    </plist>
    (the meaning of these keys is explained in the Core Foundation Keys reference).
  3. Inside Contents create another subfolder named MacOS.
  4. Save the following to a file called FirefoxLauncher in the MacOS folder:
    #!/bin/bash
    /Applications/Firefox.app/Contents/MacOS/firefox-bin -no-remote -P work &
    Adjust the path to Firefox and the profile name as appropriate.
    Update: You may need to prepend arch -i386 to the command if you're trying to run newer Firefox (version 4 and later) on Mac OS X 10.5.
    Update 2: (thanks to Daniel Beck on superuser.com for this tip) you can use open instead to avoid hardcoding the path to the application and the binary name:
    open -n -a Firefox.app --args -no-remote -P work
  5. Run chmod u+x /Applications/FirefoxWork.app/Contents/MacOS/FirefoxLauncher in the terminal to make the script executable.
  6. Now test if the program runs by executing open /Applications/FirefoxWork.app.
    • If you get an error saying "LSOpenFromURLSpec() failed with error -10810 for the file /Applications/FirefoxWork.app.", most probably the script couldn't be run - either the name in CFBundleExecutable parameter didn't match the actual script name in MacOS or the file doesn't have the execute bit set (see chmod command above).
      If you edited Info.plist, be sure to touch FirefoxWork.app to invalidate OS X's cache. 
  7. Voila! You can now drag FirefoxWork.app to the dock or run the application via QuickSilver and it doesn't take a second to run the shell script.