How to build a firefox extension
before we start, we can introduce a development tool firstly
web-ext
which is a command line tool designed to speed up various parts of the extension development process, making development faster and easier.
you can install it to global environment.
npm install --global web-ext
Now, we create a folder name “firebox-extension-demo”, and create a manifest.json
file. we can build a firefox extension start from a manifest.json
, the file is the enterance of a extension. The manifest.json
should include the name
, version
,manifest_version
at least.
"name": "996.ICU",
"version": "1.0",
"manifest_version": "1.0",
"description": "firefox version of 996.ICU",
"icons": {
"48": "/icons/icon_48.png",
"96": "/icons/icon_96.png"
},
"content_scripts": [{
"matches": [],
"js": ["content.js"]
}],
"background": {
"scripts": ["background.js"],
"page": ["background-page.htmml"]
}
“icons” will add a icon a firefox’s extension page, “content_scripts” ‘s value will be loaded to the “matches” URLs.
Here is an image to descripe how a extension be structed;
what’s content script?
A content script is a part of your extension that runs in the context of a particular web page. Content scripts can access and modify the page’s DOM, just like normal page scripts can. Content scripts can only access a small subset of the WebExtension APIs. And the background script can access the full WebExtension APIs.
then we go to the root folder of firefox extension, use command
web-ext run
This starts Firefox and loads the extension temporarily in the browser, and will auto reload when your source files are edited.
and we build a content.js
file
Those are subset of WebExtensions API which content script can access to: extenstion.getURl,extension.inIncognitoContext, runtime APIs, includes connect(), getManifest(), getUrl(), onConnect(), onMessage() and sendMessage(), all storage APIs.
what’s background page?
Sometimes, extensions often need to maintain long-term state or perform long-term operations independently of the lifetime of any particular web page or browser window. That is what background scripts are for.
You can descript a background script or you can descript a background page then load the background script. This can support the ES6 module.
Background page can access to window
glogal varible, full DOM API and full WebExtensions API.
what’s extensiton page(standlong)?
The Firefox support three kinds of page to build a extension. they are slides, popup window and options page. And the support a special page to build your app.
you can use window.create()
or tab.create()
to create a standlong page.
This page can include html, css and javascript. it can access all full WebExtensions API too. But it has it’s own global.
demo to create a extension page
const createData = {
type: 'detached_panel', // "normal", "popup", "panel", "detached_panel"
url: 'standlong.html',
width: 345,
heigt: 500,
}
browser.window.create(createData)
How content script communicate with background script?
- one-off message.
content => background
browser.runtime.sendMessage(extensionId, message, options);
browser.runtime.onMessage.addListener(function(message, sender, sendRespone) {});
background => content
browser.tabs.sendMessage(tabId, message, options);
browser.runtime.onMessage.addListener(function(message, sender, sendRespone) {});
- connection-based messaging.
This is kind of longer-lived connection between the two contexts
content => background
// content
browser.runtime.connect({});
// background
browser.runtime.onConnect.addListener(function(portFromCS) {
portFromCS.onMessage.Listener(funciton(message){
console.log('message from content', message);
});
});
How content script communicate with page script?
content script can’t access to page’s script directly, but it can use DOM window.postMessage() API and window.addEventListener API to access page’s script indirectly.
pagg => content
// page
window.postMessage(message, targetOrigin);
// content
window.addEventListener('message', function(event) {
console.log('message from page script', event.data);
})
content to page is the same.