Plugins are really just a tiny web apps that run in a popup.
To load your local extension in Chrome:
- open up extensions page by putting
chrome://extensions/
in the address bar - check developer mode at the top
- click load unpacked extension and select the folder your extension is in
To load your local extension in Firefox:
- download and install a Nightly build of Firefox
- create a new profile for testing and development
- visit
about:config
and setxpinstall.signatures.required
to false - you also need to explicitly declare it as compatible with Firefox by adding an applications key to your manifest:
"applications": {
"gecko": {
"id": "YOUR_ADDON_ID"
}
}
Set "YOUR_ADDON_ID" to a made-up string formatted like "ext@example.org".
After that you can test your extension locally.
Plugin file structure:
- manifest.json
An extension requires a manifest file to define the structure, permissions, icons and other metadata (like name, version, description). It’s just a JSON file.
"permissions": [
"tabs",
"storage",
"<all_urls>"
]
You also need to add background page, which is a js file that is loaded as long as the extension is installed.
You can set “persistent”: false
to only load the file when needed, freeing up memory when the page is idle (not available in Firefox).
"background": {
"scripts": ["js/background.js"],
"persistent": false
}
Next, you define commands to listen to, like a key combination:
"commands": {
"link1": {
"suggested_key": {
"default": "Shift+Alt+1",
"mac": "MacCtrl+1"
},
"description": "Link1 Hotkey"
}
}
- popup.html
this is the html file used by the popup that appears after clicking plugin icon
- js/popup.js
This is a script included in the popup.html file. You can use here browser API that you have defined permissions to in manifest file (if you’re writing for Chrome use chrome
object, if for Firefox browser
)
document.addEventListener('DOMContentLoaded', function() {
chrome.storage.local.get('urls', (result) => {
[1, 2, 3, 4].forEach((i) => {
document.getElementById(`input${i}`).value = result.urls[i-1];
});
});
- background.js
This is where you actually listen to events and do whatever your plugin is supposed to do, you can use the same API as in popup.js
Differences between Chrome and Firefox:
- Firefox has
browser
object, Chromechrome
- Many of the APIs are asynchronous. In Chrome, asynchronous APIs use callbacks to return values, and
runtime.lastError
to communicate errors:
function logCookie(c) {
if (chrome.extension.lastError) {
console.error(chrome.extension.lastError);
} else {
console.log(c);
}
}
chrome.cookies.set(
{ url: 'https://developer.mozilla.org/' },
logCookie
);
In Firefox you can use promises:
function logCookie(c) {
console.log(c);
}
function logError(e) {
console.error(e);
}
var setCookie = browser.cookies.set(
{ url: 'https://developer.mozilla.org/' }
);
setCookie.then(logCookie, logError);
- Firefox does not support using
alert()
,confirm()
, orprompt()
from background pages. - To allow easier porting, Firefox also supports
chrome
and callbacks. That means that in many cases Chrome plugins will just work in Firefox without any changes. However, you should usebrowser
as it’s a part of the WebExtensions standard. - Specific differences in the APIs are listed here
Sources:
https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Chrome_incompatibilities https://medium.com/@aidobreen/building-a-simple-chrome-extension-1b8a0fca3ca6 https://hacks.mozilla.org/2015/10/porting-chrome-extensions-to-firefox-with-webextensions/