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.js
1 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