2

I've made a restartless add-on that is a CustomizableUI widget based on custom XBL elements. For an upcoming version I have altered the main XBL element <slyzoom>.

However, when I test the upgrade and inspect the markup with the DOM Inspector, the main XBL element is not refreshed in currently opened windows — only in newly opened windows the XBL element is expressed as intended.

I'm not entirely sure whether the problem lies with CustomizableUI not refreshing properly, or with the XBL bindings not refreshing properly.

And, although I don't have to restart Firefox, opening a new window for upgrade changes to take effect still kind of defeats the purpose of having a restartless add-on, for me.

Another question, by Noitidart, seems to hint at a similar problem, although Noitidart seems to use a slightly different approach of loading bindings rules, so I'm not entirely sure my problem is exactly the same.

Can you shed a light on where the problem most likely lies?

My bootstrap.js1 file is fairly involved, so I'll only put a simplified, slimmed down version here, with only startup() and shutdown() and with what I think are the most important aspects of getting it to work (see inline comments for additional commentary):

const Cc = Components.classes;
const Ci = Components.interfaces;
const Cu = Components.utils;

const NSXUL            = 'http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul';
const URI_CSS_BINDINGS = 'chrome://slyzoom/content/bindings.css';

let ioService      = Cc[ '@mozilla.org/network/io-service;1' ].getService( Ci.nsIIOService );
let windowMediator = Cc[ '@mozilla.org/appshell/window-mediator;1' ].getService( Ci.nsIWindowMediator );

let styleSheetUri = ioService.newURI( URI_CSS_BINDINGS, null, null );

function startup( data, reason ) {

  let CustomizableUI = Cu.import( 'resource:///modules/CustomizableUI.jsm', {} ).CustomizableUI;

  // create the widget, this all works fine
  CustomizableUI.createWidget( {
    id: 'slyzoom',
    type: 'custom',
    defaultArea: null,
    onBuild: function( document ) {
      let window      = document.defaultView;
      let windowUtils = window.getInterface( Ci.nsIDOMWindowUtils );

      // load the XBL bindings stylesheet in the window where my widget is being build
      windowUtils.loadSheet( styleSheetUri, Ci.nsIDOMWindowUtils.AUTHOR_SHEET );

      let toolBarItemAttributes = {
        id: 'slyzoom',
        label: 'SlyZoom',
        title: 'SlyZoom',
        removable: 'true',
        overflows: false
      }
      let toolBarItem = document.createElementNS( NSXUL, 'toolbaritem' );
      let slyZoom     = document.createElementNS( NSXUL, 'slyzoom' );

      for( let attributeName in toolBarItemAttributes ) {
        toolBarItem.setAttribute( attributeName, toolBarItemAttributes[ attributeName ] );
      }
      toolBarItem.appendChild( slyZoom );

      let listener = {
        onWidgetInstanceRemoved: function( id, widgetDocument ) {
          if( id == this.id && widgetDocument == document ) {
            CustomizableUI.removeListener( listener );

            // unload the XBL bindings stylesheet from the window where my widget is being removed
            windowUtils.removeSheet( styleSheetUri, Ci.nsIDOMWindowUtils.AUTHOR_SHEET );
          }
        }.bind( this ),
      };
      CustomizableUI.addListener( listener );

      return toolBarItem;
    }
  } );
}


// I thought everything in here would be enough to force a reload in startup(), but apparently it isn't
function shutdown( data, reason ) {

  if( APP_SHUTDOWN == reason ) {
    return;
  }

  let CustomizableUI = Cu.import( 'resource:///modules/CustomizableUI.jsm', {} ).CustomizableUI;

  // I thought this would destroy any DOM instance of my widget/XBL elements
  // and it actually does; I know this because I log messages
  // in the destructor of the XBL elements,
  // but this doesn't seem to be enough
  CustomizableUI.destroyWidget( 'slyzoom' );

  // unload the XBL bindings stylesheet from the every navigator window;
  // this doesn't do the job I expected it to do either
  let domWindows = windowMediator.getEnumerator( 'navigator:browser' );
  while( domWindows.hasMoreElements() ) {
    let domWindow   = domWindows.getNext();
    let windowUtils = domWindow.getInterface( Ci.nsIDOMWindowUtils );
    windowUtils.removeSheet( styleSheetUri, Ci.nsIDOMWindowUtils.AUTHOR_SHEET );
  }
}

1) follow the link to view the complete version

Alexis King
  • 43,109
  • 15
  • 131
  • 205
Codifier
  • 354
  • 1
  • 14
  • The firfox-addon tag is the most important ones. The firefox-addon-restartless tag is redundant no one checks that, it should be merged to firefox-addon. I editted in the tag you should get more views now. Ill read this later too it looks like something i might be able to help with. – Noitidart Feb 21 '15 at 15:45
  • @Noitidart Thanks Noitidart! I appreciate any help I can get with this, cause with this one I'm not entirely sure where to look. – Codifier Feb 21 '15 at 20:09
  • Yea man XBL errors are sometimes hard to debug cuz its so funky. Im a bit busy but Ill definitely try to get to this. :) – Noitidart Feb 21 '15 at 23:46
  • Thanks Noitidart! Take your time, of course. And yeah: XBL can get a bit complex. In the meanwhile, is the question of yours, that I mentioned in this question, related to this? Should I try to load XBL with css classes, for instance? Could that solve anything? – Codifier Feb 22 '15 at 10:47

0 Answers0