Creating a firefox plugin

Test if your firefox is ready

  1. Download Sample code by firefox
  2. install and test

Anatomy of a plugin

As in firefox documentation
Anatomy of a plugin

Ensure console.log works

To make console.log work in add on

  1. Go to about:config
  2. create key extensions.sdk.console.logLevel with value all, if not already exists
    ref

Create a new Firefox Plugin

Basically 4 steps are to be kept in mind

  1. Step 1 : Create a manifest.json file
  2. Step 2 : Create a content.js script
  3. Step 3 : Interscript communication
  4. Step 4 : Settings & Storage

Step 1 : Create a manifest.json file

Important json variables are

  1. manifest_version
  2. name
  3. version
  4. permissions
  5. browser_action
  6. content_scripts
  7. browser_specific_settings( for gecko id). Required if browser storage is used for settings(see below) Mandatory if the extension ID cannot be determined . See when you need to specify an add-on ID
    if gecko id is not set , following error might happen

    Error: Error: The storage API will not work with a temporary addon ID. Please add an explicit addon ID to your manifest. For more information see https://mzl.la/3lPk1aE. options.js:15:13

Sample manifest.json

{
  "manifest_version": 2,
  "name": "Upkar media manager",
  "version": "1.0", "description": "Adds Link to load temporarily from pc, go to about:debugging#/runtime/this-firefox",
  "homepage_url": "https://github.com/mdn/webextensions-examples/tree/master/beastify",
  "icons": {
    "48": "images/upkar48.png"
  }, 
  "permissions": [
    "activeTab",
    "storage",
    "*://mysite.com/*"
  ], 
  "browser_action": {
    "default_icon": "images/upkar32.png",
    "default_title": "Upkar media manager",
    "default_popup": "popup_files/popup.html"
  },  
  "content_scripts": [
    {
      "matches": ["<all_urls>"],
      "js": ["content_files/content.js"]
    }
  ], 
  "options_ui": {
    "page": "settings/options.html"
  },
  "browser_specific_settings": {
    "gecko": {
      "id": "addon@example.com"
    }
  }
}

Step 2: Create a content.js script

document.body.style.border = "5px solid red";

Step 3: Interscript communication

In popup.js

  1. Locate current tab to send message

    browser.tabs.query({
            currentWindow: true,
            active: true
          }).then(sendMessageToTabs).catch(onError);
    /**DEFINE ERROR FUNCTION**/       
    function onError(error) {
    console.error(`Error: ${error}`);
    }   
    /**DEFINE FUNCTION TO SEND MESSAGE**/
    function sendMessageToTabs(tabs) {
    for (let tab of tabs) {
    browser.tabs.sendMessage(
      tab.id,
      { function: 'fetchPageInfoAndPost2Server' ,post2LocalHost:post2LocalHost}
    ).then(response => {
      console.log("Message from the content script:");
      console.log(response.response);
    }).catch(onError);
    }
    }
  2. set listeners

    browser.runtime.onMessage.addListener(function (message, sender, sendResponse) {
  3. send reply message to content

    sendResponse({
            data: "Popup here, I am fine, thank you. How is life in the background?"
          }); 

    In content.js

  4. add listener

    /**
    * Listen for messages from the background/popup script.
    * Call "insertBeast()" or "removeExistingBeasts()".
    */
    "use strict";
    browser.runtime.onMessage.addListener(requestIsSecondArgInPopupMessage => {
      console.log("Message from the popup script:");
      console.log(request.function);
      doOperationBasedOnPopupMessage(requestIsSecondArgInPopupMessage);
      return Promise.resolve({response: "Hi from content script"});
    });
  5. send response after executing required function

          sendReply2Popup(msg)
          {
            console.log("sendReply2Popup called with  msg\r\n" +JSON.stringify(msg));
            //scripts to send message to popup and background
            function handleResponse(message) {
                console.log(`Message from the popup script:  `+JSON.stringify(message));
            }           
            function handleError(error) {
                console.log(`Error: ${error}`);
            }
                console.log("sending message to popup");
                var sending = browser.runtime.sendMessage(msg);
                sending.then(handleResponse, handleError);          
          }//sendReply2Popup(msg);

Step 4: Settings & Storage

Add manifest.json keys to setup a settings page

  1. in manifest.json, add the following
  "options_ui": {
    "page": "options.html"
  },
  "permissions": ["storage"],
  "browser_specific_settings": {
    "gecko": {
      "id": "addon@example.com"
    }
  }
  1. Add options.html
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
  </head>
  <body>
    <form>
        <label>Border color<input type="text" id="color" ></label>
        <button type="submit">Save</button>
    </form>
    <script src="options.js"></script>
  </body>
</html>
  1. Create options.js
function saveOptions(e) {
  e.preventDefault();
  browser.storage.sync.set({
    color: document.querySelector("#color").value
  });
}
function restoreOptions() {
  function setCurrentChoice(result) {
    document.querySelector("#color").value = result.color || "blue";
  }
  function onError(error) {
    console.log(`Error: ${error}`);
  }
  let getting = browser.storage.sync.get("color");
  getting.then(setCurrentChoice, onError);
}
document.addEventListener("DOMContentLoaded", restoreOptions);
document.querySelector("form").addEventListener("submit", saveOptions);

And in content.js

  1. Add code to retrieve from storage
    function onError(error) {
    console.log(`Error: ${error}`);
    }
    function onGot(item) {
    let color = "blue";
    if (item.color) {
    color = item.color;
    }
    document.body.style.border = "10px solid " + color;
    }
    let getting = browser.storage.sync.get("color");
    getting.then(onGot, onError);

References

  1. ref 1 intro
  2. ref 2 more features
  3. Interscript communication
  4. Interscript communication with promise, Promise reference
  5. For setting up a settings page with storage
  6. Anatomy of a firefox plugin
  7. Background scripts
  8. Page action