A boilerplate for creating a devtools extension for multiple browsers from a single code base.
Currently Fuse will build bare-bones devtools extensions for:
- Firefox (restartless)
- Chrome
- Opera
Fuse requires Node.js and npm so you'll need to make sure you have them installed before going any further.
npm install
config/firefox.json
- give your extension a unique ID (email address syntax)
The quickest way to get started is to run the build task. This will lint, test and build the extensions ready for installation.
grunt build
If you want to build individual extensions you can run:
grunt core
grunt core chrome
grunt core firefox
grunt core opera
Linting is done with JSHint. To lint all project files, use the lint
alias task:
grunt lint
Fuse uses Jasmine for tests. To run all project tests, use the test
alias task:
grunt test
First, make sure you've built the extension you want to install then follow the instructions below.
Browse to chrome://extensions, tick the 'Developer mode' option, click 'Load unpacked extension' and select the build/chrome
directory. If all goes well, when you open/restart devtools you should see your extension tab in the devtools pane.
Browse to opera://extensions, tick the 'Developer mode' option, click 'Load unpacked extension' and select the build/opera
directory. If all goes well, when you open/restart devtools you should see your extension tab in the devtools pane.
Firefox requires extensions to be signed before they can be enabled in the Add-on manager. During development you will need to disable add-on signing for you add-on to work. You can do this by visiting about:config
and settting xpinstall.signatures.required
to false
.
Once add-on signing is disabled, browse to your Firefox profile and find the extensions
directory:
- OSX:
/Users/[Username]/Library/Application Support/Firefox/Profiles/[profileID]/extensions
- Win:
C:\Users\[Username]\AppData\Roaming\Mozilla\Firefox\Profiles\[profileID]\extensions
In this directory create a new text file with a name that matches the extension ID (the value in config/firefox.json
). Open this new file in a text editor and paste the path to the Firefox build directory. Now (re)start Firefox and your extension tab should appear in the devtools pane.
Fuse uses a grunt watch task to monitor your source files so they can be tested and rebuilt as you make changes. Once you've made your changes you'll need to restart devtools to see your changes.
grunt build watch
Note: If you modify the core or extension source without running the watch task you'll need to manually build the extension.
The main body of work for your extension will be done in the following files:
Markup:
- Firefox:
src/firefox/chrome/panel.xul
- Chrome / Opera:
src/chromium/panel.html
JavaScript:
- Core API
src/core/core.js
- Firefox:
src/firefox/chrome/js/main.js
- Chrome / Opera:
src/chromium/js/main.js
CSS:
- Firefox:
src/firefox/skin/css/main.css
- Chrome / Opera:
src/chromium/css/main.css
Fuse can package your extension into a standalone installable files. To package everything, ensure your have run the relevant build tasks and then run:
grunt package
If you need to package individual extensions:
grunt package:chrome
grunt package:opera
grunt package:firefox
When packaging for the first time, both Chrome and Opera will export a private key (a .pem
file) to the /config
directory. You'll need to keep these files safe as they will be required when you release future versions of your extension. NEVER add these files to your public repos.
If your moving an existing extension to Fuse you can copy your private key files here:
- For Chrome:
/config/chrome.pem
- For Opera:
/config/opera.pem
NOTE: Opera will fail to package an extension if it is already running. This is a known issue that Opera developers are working on. NOTE: Opera will fail to terminate when packaging with an existing private key. This causes the extension package task to hang. To work around this you'll need to terminate Opera manually. A bug has been submitted (DNA-44534).
Your browser specific configuration files go here.
The assets directory contains the assets that will be shared across all extensions. Typically, this is where you'll store you various icons and common UI elements. During build these files are copied into each extensions relevant img
directory.
Since these assets don't physcially exist in the src/{extension}
directories so you need to reference them using their build location. If you wanted to reference the icon at /assets/img/icon-128.png
you would use the following paths (which are relative to /build/{browser_extension}
):
- In Chrome
img/icon-128.png
- In Opera
img/icon-128.png
- In Firefox
skin/img/icon-128.png
This is where your localisation files live. Extensions are developed in English with the base messages defined in /lang/en.json
. When a build task is run, the .json
files in the /lang
directory are used to create the various localisation files.
In lang/en.json
:
{
greeting: "Hello"
}
In lang/fr.json
:
{
greeting: "Bonjour"
}
These strings are accessed with the browsers built-in localisation helpers:
For Chromium:
var message = chrome.i18n.getMessage('greeting');
For Firefox:
var message = L10N.getStr('greeting');
CoreAPI is the backbone of your extension. It should be self-contained and not use browser specific code. During build the core files are copied into each browser extensions build directory:
- For Chrome:
js/core.js
- For Opera:
js/core.js
- For Firefox:
chrome/js/core.js
The chromium directory contains all the files required to create the extensions for Google Chrome and Opera. During build the following dependencies are merged into the directory:
For Chrome:
/assets/img/*
=>/chrome/img/*
/build/core/core.js
=>/chrome/js/core.js
lang/*.json
=>/chrome/_locales/*/messages.json
(formatting changes)
For Opera:
/assets/img/*
=>/opera/img/*
/build/core/core.js
=>/opera/js/core.js
lang/*.json
=>/opera/_locales/*/messages.json
(formatting changes)
The firefox directory contains all the files required to create the Firefox extension. During build the following dependencies are merged into the directory:
/assets/img/*
=>/firefox/skin/img/*
/build/core/core.js
=>/firefox/chrome/js/core.js
lang/*.json
=>/locale/*/strings.properties
(formatting changes)
This is where your unit tests live.