Programming » Firefox Addons

Simple Restartless Addon

This addon will add a new shortcut for Close Other Tabs command

1. Create a folder with name close-other-tabs-test.

2. Create file install.rdf to give the addon a name, id and application binding (Thunderbird, Firefox, Android)

<?xml version="1.0"?>
<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" 
     xmlns:em="http://www.mozilla.org/2004/em-rdf#">
  <Description about="urn:mozilla:install-manifest">
    <em:id>close-other-tabs-test@test.org</em:id>
    <em:name>Close Other Tabs Test</em:name>
    <em:version>1.0</em:version>
    <em:type>2</em:type>
    <em:bootstrap>true</em:bootstrap>
  
    <em:description>Closes other tabs</em:description>
    <em:creator>creator</em:creator>

    <!-- Firefox -->
    <em:targetApplication>
      <Description>
        <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
        <em:minVersion>20.0</em:minVersion>
        <em:maxVersion>36.0</em:maxVersion>
      </Description>
    </em:targetApplication>
  </Description>
</RDF>
id - any id with @
type - it's an addon (not theme)
bootstrap - it's restartless
targetApplication -> id - constant bound to Firefox

3. Create file bootstrap.js which is the entry point of the addon

const {classes: Cc, interfaces: Ci, utils: Cu}=Components

Cu.import("resource://gre/modules/Services.jsm")
Cu.import("resource://gre/modules/AddonManager.jsm")

/* **************** vars **************** */

const shortcutProps={
  id:"key_CloseOtherTest",
  key:"W",
  modifiers:"alt",
  command:"gBrowser.removeAllTabsBut(gBrowser.selectedTab)"
}
var self=this

/* **************** main functions **************** */

function startup(data,reason){
  AddonManager.getAddonByID(data.id, function(addon){
    include(addon, "content/ui.js")
    include(addon, "content/main.js")
    
    eachWindow(loadIntoWindow)                        //ui building function
    Services.ww.registerNotification(windowWatcher)
  })
}

function shutdown(data,reason){
  if(reason==ADDON_DISABLE){
    Services.ww.unregisterNotification(windowWatcher)
    eachWindow(unloadFromWindow)                        //ui destroying function
  }
}

/* **************** add functions **************** */

function include(addon, path){                          //load scripts
  Services.scriptloader.loadSubScript(addon.getResourceURI(path).spec, self)
}
shortcutProps – contains the shortcut data (id and key combination to trigger the command)
startup() – runs when the addon installs and browser starts
shutdown() - runs when browser closes and addon uninstalls

include() – is used to add external .js scripts to the addon

On install/startup the function loadIntoWindow runs for each open window and loads the UI elements (adds the shortcut).

On uninstall only (which is filtered by the ADDON_DISABLE reason) the function unloadFromWindow runs for each open window and removes the UI elements (removes the shortcut).

4. Create folder named content and create files inside it.

main.js
ui.js

5. Add code to the main.js file

/* **************** ui build ***************** */

function loadIntoWindow(window){
  addKeyboardShortcut(window)
}

function unloadFromWindow(window){
  if (!window) return
  removeKeyboardShortcut(window)
}

/* **************** load functions **************** */

function eachWindow(callback){
  let enumerator=Services.wm.getEnumerator("navigator:browser")
  while (enumerator.hasMoreElements()){
    let win=enumerator.getNext()
    if (win.document.readyState==="complete") callback(win)
    else runOnLoad(win, callback)
  }
}

function windowWatcher (subject, topic){
  if (topic==="domwindowopened")
    runOnLoad(subject, loadIntoWindow)
}

function runOnLoad (window, callback){
  window.addEventListener("load", function(){
    window.removeEventListener("load", arguments.callee, false)
    callback(window)
  }, false)
}
loadIntoWindow/unloadFromWindow functions perform the startup/shutdown actions.

The addon functions only work when the active browser window is completely loaded.

5. Add code to the ui.js file

function addKeyboardShortcut(w){
  var document=w.document
  var keyset=document.createElement("keyset")
  var key=document.createElement("key")
  
  if(keyset && key){
    key.setAttribute("id", shortcutProps.id);
    key.setAttribute("key", shortcutProps.key);
    key.setAttribute("modifiers", shortcutProps.modifiers);
    key.setAttribute("oncommand", shortcutProps.command);
    keyset.setAttribute("id","closeOtherKeyset")
    
    keyset.appendChild(key);
    document.documentElement.appendChild(keyset)
  }
}

function removeKeyboardShortcut(w){
  var document=w.document
  var keyset=document.getElementById("closeOtherKeyset")
  keyset && keyset.parentNode.removeChild(keyset)
}
Here the addKeyboardShortcut() function creates XUL DOM elements and adds them to the browser DOM tree.

The removeKeyboardShortcut() function removes these elements from the tree and disables the created shortcut.

6. Now open the install.rdf file, copy the id property, create new blank file and paste the copied value as its name. So the file will be named

close-other-tabs-test@test.org

7. Open this file and paste the path to the close-other-tabs-test folder.

8. Close Firefox

9. Now go to Firefox extensions folder.

For Windows XP:
C:\Documents and Settings\[username]\Application Data\Mozilla\Firefox\Profiles\[profile-name].default\extensions\
For Windows 7:
C:\Users\[username]\AppData\Roaming\Mozilla\Firefox\Profiles\[profile-name].default\extensions\

10. And copy the close-other-tabs-test@test.org file here

Restartless Addon extensions folder

11. Open Firefox. It should display the Install Addon screen. Check Allow this installation and press Continue.

Restartless Addon install addon dialog

12. Test the addon. Open multiple tabs. Press Alt+W. All tabs except the current one should close (there could be a warning before asking permission to close multiple tabs)

Restartless Addon close tabs warning

13. Pack the addon. Go to the addon folder select all and create a .zip archive with 7-zip. Then change the extension to .xpi.

Restartless Addon zip

14. Now open Firefox, remove the installed addon, restart and drag the created .xpi package on the browser window.

Install it as a regular addon.

Restartless Addon install addon manually

Additional Information

1. Addon folder structure:

/ close-other-tabs-test
  - / content
    - main.js
    - ui.js
  - bootstrap.js
  - install.rdf

2. Project GitHub repository

3. Check the DOM structure

  1. Install DOM Inspector an Element inspector addons
  2. Holding Shift rightclick anywhere in the browser titlebar
  3. Press End or scroll down to the end of the DOM Inspector window
  4. Check the closeOtherKeyset keyset element is there.

    Restartless Addon DOM Inspector

  5. Also try to uninstall the addon and check again the DOM, the keyset should be removed.

Leave a Reply

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>