This article explains the basics of creating an add-on for FireFox using the FireFox Add-on Builder and Add-on SDK. Read more about them on the Mozilla website. As an example, I’ll use the GroupDocs add-on. (You can download the source code from Github.) It’s an advanced extension so I’ll focus on the basics and highlight a couple of interesting aspects communication between scripts. I’ll mainly look at the add-on folders data and lib in the /resources/groupdocsviewer/ folder.
Creating an add-on: main.js
The main.js file, located in the lib folder, is the entry point for the extension. It is executed when you install the add-on and then each time the browser is launched. At the top of the file is a ;ist of libraries linked in using the SDK command require():
The widget library is used to create the icon that users click to open the GroupDocs add-on’s main window.
Object data from the library called self is used to access files in the data folder. This folder holds all the JavaScript files, libraries, pictures, text files, HTML files, styles and other resources that the add-on needs.
The panel library creates the GroupDocs window that contains the add-on interface.
The passwords library stores personal information in the FireFox Password Manager.
Linking libraries, creating widget and panel
After connecting to the required libraries, the script creates a panel. This loads HTML content from the data folder and sets the dimensions of the add-on window. As well as creating the panel, any JavaScripts that the add-on uses are loaded at this point. Note that the scripts attached to the panel do not have access to the main.js context, nor does main.js have access to the panel context. More about that later. Once the panel is created, the script creates a widget. The widget is a button that can be seen in FireFox’s add-ons panel. To create the widget, define an ID, a label and an image. The image is the icon that users click to start the GroupDocs extension. Lastly, define the panel that will be launched when the icon is clicked. The code that follows the widget definition consists of message handlers.
Communication between scripts
I mentioned that the scripts that run in the add-on interface do not have access to the main.js file’s context. They also can’t call the FireFox API: the FireFox API only works within the main.js context. This means that the add-on has two execution contexts: the main.js file, which as access to the FireFox API, and script files that work with the add-on window’s DOM model. Since main.js and the scripts that run in the panel don’t have direct access to each other’s content, we need to use messages to communicate between the two. To send a messages from main.js, use the panel object’s port.emit() method. It takes two parameters: the message, as a string, and the object the message is for.
Use panel.port.emit function for sending message from main.js
To receive messages from the main.js file, use the panel class’ port.on() method. This too takes two parameters: the message, as a string, and the parameter handling function. When a message arrives, this function can take the second parameter of the sent object – port.emit().
Use panel.on function for receiving message from main.js
Credential management
GroupDocs defines a message handler for storing and removing credentials in FireFox’s Password Manager. This process illustrates how to pass messages between main.js and the GroupDocs window. The first message is received when a user logs in and has selected the Remember me option. The second message is received when a user clicks Logout. You’ll notice, in the main.js file, in the first function, that the script checks whether the user is already logged in. If they are, the panel sends a message containing the login data. This way, users do not have to log in every time they restart the browser.
Messages to other Scripts
JavaScript files connected to the panel are executed within the panel in the order that they are listed. This is important because it allows you to load any number of libraries and then also files that use those libraries. One of the files called by the main.js file to create the main panel is popup.js. It initializes handlers for all the controls in the add-on window. This file also contains the all the extension’s logic. Sending and receiving messages here is a little more complicated. The methods port.on() and port.emit() are located within the object itself, and the object is available in the global context, that is, it’s not visible to other functions or objects. Keep a reference to the object so that you can use it when you run the file. It is worth noticing that to start carrying out any actions in the popup.js file follows not in the first line of the file, but in the method which has received the message from the main.js file.
Summary
This is how it works: widgets and panels are created in main.js. Then we have a message handler that ensures that a “show” message is generated when the panel is displayed. Code in main.js catches the message and sends a similar message to popup.js. Code in popup.js catches the message and initialises the extension.
Transit of the message of 'show'
popup.js starts working as soon as the panel has been displayed and a DOM model add-on is ready to use. It functions as any site: JavaScripts respond, the DOM is modified as needed and AJAX requests are made. To interact with the FireFox API, send a message to main.js which, after working with the FireFox API, sends a message back to popup.js with the results.