Home | Blog | LegacyFox

Coaxing modern Firefox into running legacy Extensions

Firefox 57 marked a new era of the last remaining user agent, that actually puts the user first: XPCOM-based add-ons, that essentially monkey-patch the browser, were deprecated. While this is a good development for Mozilla and its users, it also left me without a usable vi-like navigation[1]. Here's how you can patch Firefox ESR 60 to accept legacy extensions again.

The easy way

Wait for Waterfox 68 to come out; it has both no requirement for add-on signing and allows some legacy extensions to work, including my beloved VimFx v0.21.0. It's fair to consider this "cheating."

The "I need it now" way

  1. Build yourself a Firefox ESR 60 using the add-on-devel configuration
  2. In about:config set extensions.legacy.enabled to true
  3. Optionally, set xpinstall.signatures.required to false

Please be aware, that support for 60ESR ends on 2019-10-22.


That's all. Here is where you should probably stop reading. Here's a cat picture to distract you!

cat picture
Sir William, by the talented Mikhail Vasilyev.

The stubborn way

If for some reason (like wanting to use your distribution's prepackaged Firefox) this won't cut it for you, there is a more elaborate and less reliable way. This method also worked with regular (non-ESR) versions of Firefox up to v64[2], but using such an outdated browser is not recommended.

First off: This is a stupid idea. Mozilla prevents you from doing this for good reasons. But here we go:
Let's start off by setting some values in about:config. There is a file that we can use to automatically set them for us. It is located in Firefox's profile directory, which is usually in ~/.mozilla/firefox/, followed by a random string of characters. If you've got more than one, have a look at profiles.ini; one should have Default=1 set.

~/.mozilla/firefox/$PROFILE_NAME/user.js
user_pref("extensions.legacy.enabled", true);
user_pref("xpinstall.signatures.required", false);
user_pref("app.update.enabled", false);  // would override our patched omni.ja

Then we need to patch omni.ja[3], a zip archive that contains much of Firefox' runtime Javascript. In it, there are a bunch of configuration options, including the flag that checks, if you're allowed to enable legacy extensions.

patch-firefox.sh
#!/bin/sh -ex
FIREFOXDIR=/usr/lib64/firefox/  # must be absolute!
TEMP_OMNI=/tmp/omni

rm -rf "$TEMP_OMNI"
mkdir "$TEMP_OMNI"
cd "$TEMP_OMNI"

# unzip will complain about the archive, so ignore exit code
unzip -q "$FIREFOXDIR/omni.ja" ||:

# ALLOW_LEGACY's values is two lines below; hence 'n;n'
sed -i '/MOZ_ALLOW_LEGACY_EXTENSIONS/{n;n;s/false/true/}' \
  modules/AppConstants.jsm

zip -qr9XD "$TEMP_OMNI.ja" -- *

sudo cp "$FIREFOXDIR/omni.ja" "$FIREFOXDIR/omni.ja.bak"
sudo mv "$TEMP_OMNI.ja" "$FIREFOXDIR/omni.ja"

You'll have to run this script after every Firefox update, preferrably automatically. Make sure, the path in FIREFOXDIR is correct for your distribution. A big shout-out to Akkana Peck, on whose code this is based on.

This will let your old add-ons run again, but chances are, they rely on some of Gecko's APIs, which may have been removed and some changes to them might be required. Mozilla won't sign legacy extensions for you any more, so you'll need to persuade Firefox somehow. So we need to disable Add-on signing. This comes courtesy of a user on "Hacker" "News"[5]. I'm too lazy to incorporate this into the above script (patches welcome!), and I'm not sure if you'll need all those scripts to do it, but it works for me™. Depending on your distro, the paths may vary slightly.

/usr/lib64/firefox/config.js
// keep this comment
try {
  Components.utils
    .import('resource://gre/modules/addons/XPIDatabase.jsm', {})
    .XPIDatabase['SIGNED_TYPES'].clear();
} catch (ex) {
  Components.utils.reportError(ex.message);
}
/usr/lib64/firefox/defaults/pref/config-prefs.js
pref("general.config.obscure_value", 0);
pref("general.config.filename", "config.js");
pref("general.config.sandbox_enabled", false);

Footnotes

I hate footnotes. But I won't bore/distract/confuse you with my (attempt at) snarky humour, unless you really want me to. Press your user agent's hotkey for window.history.back() to get back to where you were coming from.