October 15th, 2019
Firefox extension development
I’ve been working as a developer on the Adblock Plus browser extension for the past 5 years or so. While I test my work on a bunch of different platforms, I’ve mostly been using Chrome during development and as my main browser. That’s now going to change, I am switching to Firefox.
I spent some time last week making the switch, I thought I’d write up my notes in case any other extension developers (cough Sebastian) are interested in making the switch too.
Mozilla have written some great documentation, I recommend reading through extensionworkshop.com before you go any further. While it seems to be aimed at someone starting out with extension development, its still well worth a read. There are quite a few cool Web Extension APIs unique to Firefox which are detailed. You will want to read up on their web-ext command line tool too. Also, the explanation of Firefox’s “X-ray vision” (the equivalent of Chrome’s “isolated worlds”) for content scripts is important to read.
I recommend installing the Developer Edition of Firefox. It’s built from the Beta channel, but additionally has some developer-only options enabled. It’s good to test against the upcoming browsers as an extension developer anyway - better to catch problems before your users! - but specifically, the Developer Edition is a necessity for extension development IMO for reasons I’ll go into in a minute.
When I was first getting started, I found Firefox ran kind of sluggishly to the point of feeling almost unstable. At one point, this got so bad that the entire Firefox window would not render at all. Initially, it looked like the browser had crashed, but then I realised it was actually still running… That seemed quite unusual, so on a whim, I killed my window compositor - Compton. Sure enough, Firefox immediately reappeared. Better yet, Firefox then felt much more responsive too. I can’t find it now, but one comment online mentioned that Compton can clash with applications using 3d acceleration as Firefox does. Perhaps I had configured it incorrectly, but I’ve just stopped using Compton for now. Hopefully, XFCE’s improved built-in compositor will be enough to avoid screen tearing instead.
When loading an unpacked extension by hand, I was surprised that you have to
select its manifest.json
file manually, instead of just selecting the
extension’s directory. While a relatively minor annoyance it does seem pointless
so I’ve filed this bug.
Since I’m mostly working on one extension, I want to be able to keep the
extension running all the time in order to “dogfood” my work.
In Chrome that’s pretty easy to do, you toggle developer mode, load the unpacked
extension and then it’ll stick around just like any other extension. With
Firefox it’s a bit harder. While you can launch Firefox with your extension
using the web-ext
tool, or by loading it as a temporary Add-on, the
extension and its settings won’t persist the next time you start Firefox.
Having a persistent unpacked extension is possible in Firefox though, while Mozilla’s docs touch on how I think this is one area the docs could be improved. Here’s how to do it:
- Browse to
about:config
and set thexpinstall.signatures.required
preference tofalse
. (This part won’t work with regular Firefox builds, which is why I recommend using the Developer Edition.) - Figure out where your Firefox profile directory is by clicking Help -> Troubleshooting Information -> Profile Directory.
- Ensure your extension’s manifest defines an extension ID, specifically
it needs to be in
applications.gecko.id
. - Write the path of your unpacked extension directory to a text file. Name the file your extension’s ID (no file extension) and put it in the extensions subdirectory of your Firefox’s profile. In other words, type something like this:
echo "~/my-unpacked-extension/" > ~/.mozilla/firefox/PROFILEDIR/extensions/EXTENSIONID"
- Restart Firefox.
- Browse to
about:addons
and enable your extension.
One thing that’s quite different when developing extensions in Firefox vs Chrome
is how the consoles for the various extension contexts are exposed. In Chrome,
you must click the “background page” button from chrome://extensions/
to open
the console for the extension’s background page. Then right-click on the
extension’s icon and click “Inspect pop-up” to debug the popup window. You can
open the console for the options or other extension pages like you would any
other webpage. Then finally to debug content scripts you open the console for a
webpage, but then use the context drop-down on the top left to switch to the
content script’s context.
Firefox instead provides a unified Toolbox window for the extension. From
about:addons
you select “Debug Add-ons” and from there you can click the
“Inspect” button and a toolbox window will open. From there you can
click on the icon and switch between almost all of the extension’s
contexts, even things like the options page. What’s more, when switching
contexts with the Firefox developer tools you’re switching the context for all
the tools, not just the console! So for example, the element inspector and all
the other tools change too - cool!
Firefox’s extension Toolbox is a boon, but there are a few caveats…
I found that the background consoles for extensions are a little noisier on Firefox than on Chrome. Unrelated exceptions seem to show up there. For example, with Adblock Plus and LastPass installed, I see exceptions relating to LastPass in the background console for Adblock Plus… weird. I guess before investigating why an exception has happened… first, check that it actually relates to your extension! The behaviour seems undesirable, so I’ve filed a bug.
Debugging your extension’s popup window is also a little trickier. In Chrome, when you click to inspect the popup, the console opens and the popup window stays open until you close it. That’s not the case in Firefox, you need to first select the “Disable Popup Auto-Hide” button from the hamburger menu of your extension toolbox. Then you need to open your popup window, then finally select your popup window from the context switcher in your extension toolbox. Surprisingly that will also cause all extension popups to become sticky. Before I disabled Compton I found the behaviour even more bizarre, Firefox menus were also staying open and eventually rendering stopped entirely.
I found that breakpoints in my popup scripts wouldn’t fire until I refreshed the entire popup window. To be fair, this is also a problem I’ve experienced when debugging popup scripts in Chrome. I’ve found this troublesome when investigating problems in the past however since refreshing the popup window from its console causes the active window to be different.
Unfortunately, the context switcher in Firefox’s developer tools doesn’t yet support content scripts. Though if you open the developer tools for a page, you will see your content scripts listed, their output in the console etc. One trick I found on Bugzilla is to create a breakpoint in one of your content scripts, then once it’s triggered hit Esc to open the console and evaluate what you need to in the content script’s context.
Anyway, I’m really enjoying playing with Firefox again. The developer tools have some great functionality that’s missing from the other browsers. I also can’t wait to try some of the extra Web Extension APIs which it supports. If it’s been a while since you’ve tried Firefox as a web/extension developer it’s well worth giving it another shot.