2

我制作了一个无需重启的CustomizableUI插件,它是一个基于自定义XBL元素的小部件。对于即将发布的版本,我更改了主要XBL元素<slyzoom>

但是,当我测试升级并使用 DOM Inspector 检查标记时,主要XBL元素不会在当前打开的窗口中刷新 - 只有在新打开的窗口中,该XBL元素才会按预期表达。

我不完全确定问题是否在于CustomizableUI没有正确刷新,或者XBL绑定没有正确刷新。

而且,虽然我不必重新启动 Firefox,但打开一个新窗口以使升级更改生效仍然有点违背了拥有无需重新启动的附加组件的目的,对我来说。

Noitidart 提出的另一个问题似乎暗示了一个类似的问题,尽管 Noitidart 似乎使用了一种稍微不同的加载绑定规则的方法,所以我不完全确定我的问题是否完全相同。

你能说明问题最可能出在哪里吗?

我的1文件相当复杂,所以我只会在这里放一个简化的、精简的版本,只有和和我认为是让它工作的最重要的方面(有关其他评论,请参阅内联评论):bootstrap.jsstartup()shutdown()

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)点击链接查看完整版本

4

0 回答 0