One of the changes we made for Pearl Crescent Page Saver 0.9.3 was to automatically add our “Save Page Image” toolbar item to the right side of the Firefox navigation toolbar. We thought that would be easy to do, but (like many programming tasks) getting everything to work correctly was trickier than expected.

Page Saver toobar item

Problem 1: Adding the item by updating the navigation toolbar’s .currentSet property caused many of the toolbar items to stop working (for example, it no longer worked to load a new page from the URL bar). Not good. Solution: call BrowserToolboxCustomizeDone() to tell Firefox to reinitialize the toolbars. This is a somewhat sneaky thing to do; Firefox should really provide a clean way for extensions to update the toolbars (in fact, there is an open bug on this topic).

Problem 2: (fallout from the solution to problem 1) Calling BrowserToolboxCustomizeDone() immediately after the window load event fired caused exceptions to be thrown (Firefox had not initialized everything yet). Solution: use setTimeout() to introduce a short delay before adding the toolbar item. I don’t much care for using setTimeout() this way, but it works.

We also set a Boolean preference so the toolbar item will only be installed once (if the user removes it, we don’t want it to mysteriously reappear). Here is the code:

const kPrefPrefix = "pagesaver.";
const kPrefTBItemInstalled = kPrefPrefix + "toolbariteminstalled";
 
window.addEventListener("load", SavePageInit, false);
 
function SavePageInit()
{
  var tbItemInstalled = nsPreferences.getBoolPref(kPrefTBItemInstalled, false);
  if (!tbItemInstalled)
    setTimeout("SavePageAddToolbarItem();", 0);
}
 
function SavePageAddToolbarItem()
{
  const kToolBarID = "nav-bar";
  const kTBItemID = "tb-save-page-image";
  var tbElem = document.getElementById(kToolBarID);
  var tbItemElem = document.getElementById(kTBItemID);
  if (tbElem && !tbItemElem)
  {
    var newSet = tbElem.currentSet + "," + kTBItemID;
    tbElem.setAttribute("currentset", newSet);
    tbElem.currentSet = newSet;
    document.persist(kToolBarID, "currentset");
    nsPreferences.setBoolPref(kPrefTBItemInstalled, true);
 
  try {
      BrowserToolboxCustomizeDone(true);
    } catch (e) {}
  }
}

The try/catch around the BrowserToolboxCustomizeDone() call is not really necessary, but it insulates us a little bit from future Firefox changes.

I hope this information helps someone else.

References:

2 thoughts on “Programmatically adding items to the Firefox toolbar”
  1. I am using a very similar code in my Wengo extension for Firefox. Hey, there are not two different ways of doing that.

Comments are closed.