Как мне подождать, пока все области будут зарегистрированы с помощью CustomizableUI в bootstrap.js::startup()?

Я создаю беспомощное дополнение, которое является CustomizableUI виджет.

Когда я звоню CustomizableUI.createWidget() в течение startup(), Я хочу defaultArea свойство быть одним из выбора предпочтительных областей. В настоящее время я достигаю этого примерно так:

// ordered from most to least preferred
let preferredAreas = [
  'ctraddon_addon-bar',
  'ctraddon_extra-bar',
  CustomizableUI.AREA_BOOKMARKS,
  CustomizableUI.AREA_NAVBAR,
  // null basically translates to 'PanelUI-contents'
  // but this makes it easy to test later on
  null
];

let registeredAreas = CustomizableUI.areas;
let preferredArea;
for( let i = 0, l = preferredAreas.length; i < l; i++ ) {
  preferredArea = preferredAreas[ i ];
  if( registeredAreas.indexOf( preferredArea ) > -1 ) {
    break;
  }
}

if( !preferredArea ) { // i.e. null
  /* on first run: notify user that we were unable to find a preferred area */
}

CustomizableUI.createWidget( {
  id: 'myAddon',
  type: 'custom',
  defaultArea: preferredArea,
  /* etc */
} );

Другими словами: я проверяю, присутствует ли предпочтительная область. Это работает в значительной степени, как ожидалось, в startup()сразу после установки, потому что в основном все области интереса (из других расширений, таких как Classic Theme Restorer) уже зарегистрированы. Однако, когда мое дополнение уже установлено и Firefox запускается, CustomizableUI.areas еще не заполнен всеми интересующими областями (возможно, потому что мое расширение загружается раньше, чем расширение, которое регистрирует интересующие области).

Я пытался использовать mostRecentWindow.addEventListener( 'load', /* etc */ ), где mostRecentWindow это возвращаемое значение nsIWindowMediator.getMostRecentWindow( 'navigator:browser' ), но:

  1. при запуске приложения mostRecentWindow будет null
  2. при установке дополнения mostRecentWindow не уволит load событие больше

Итак, мой вопрос: каков простой и эффективный способ ожидания звонка CustomizableUI.createWidget() пока весь соответствующий код не загружен?


В конечном итоге я сделал следующее (что также предложил Noitidart), что, похоже, работает:

let createWidget = function() {
    /* all the preferredArea and CustomizableUI.createWidget() stuff from above */
}

let mostRecentBrowserWindow = windowMediator.getMostRecentWindow( 'navigator:browser' );
if( null == mostRecentBrowserWindow ) {
  let windowListenerWidget = {
    onOpenWindow: function( wrappedWindow ) {
      windowMediator.removeListener( windowListenerWidget );
      let domWindow = wrappedWindow.QueryInterface( Ci.nsIInterfaceRequestor )
                                   .getInterface( Ci.nsIDOMWindow );
      domWindow.addEventListener( 'load', function onWindowLoad( event ) {
        this.removeEventListener( 'load', onWindowLoad );
        createWidget();
      } );
    }
  }
  windowMediator.addListener( windowListenerWidget );
}
else {
  createWidget();
}

1 ответ

Что вам нужно сделать, это добавить слушателя для onAreaNodeRegistered, В обратном вызове создайте свой виджет.

Смотрите MDN:: CustomizableUI.jsm - addListener()

onAreaNodeRegistered и onAreaNodeUnregsitered не находятся на mdn, так что вот определения: http://mxr.mozilla.org/mozilla-release/source/browser/components/customizableui/src/CustomizableUI.jsm#2704

2704    *   - onAreaNodeRegistered(aArea, aContainer)
2705    *     Fired after an area node is first built when it is registered. This
2706    *     is often when the window has opened, but in the case of add-ons,
2707    *     could fire when the node has just been registered with CustomizableUI
2708    *     after an add-on update or disable/enable sequence.
2709    *   - onAreaNodeUnregistered(aArea, aContainer, aReason)
2710    *     Fired when an area node is explicitly unregistered by an API caller,
2711    *     or by a window closing. The aReason parameter indicates which of
2712    *     these is the case.
2713    */

Так что для реализации сделайте это:

Сначала проверьте, существует ли область, которую вы хотите. Если это не так, добавьте слушателя. И в слушателе сделать виджет создания:

var targetAreaId = 'blah'; //the id of area you want test for, meaning the area you want to add your widget too, targetAreaId can be CustomizableUI.AREA_NAVBAR, basically its the id (first arg) argument of CustomizableUI.registerArea('blahIdHere'..

function createMyWidget() {
  CustomizableUI.addWidget({
     id: "edit-controls",
    type: "custom",
    defaultArea: targetAreaId,
    onBuild: function(aDocument) {}
    //........ blah blah balh
  })
}


if (CustomizableUI.areas.indexOf(targetAreaId) > -1) { // customizableUI.areas is an array for example for me it is:`Array [ "PanelUI-contents", "nav-bar", "toolbar-menubar", "TabsToolbar", "PersonalToolbar", "addon-bar", "thePuzzlePiece-addon-bar" ]`
  createMyWidget();
} else {    
    var myCustUiListener = {
      'onAreaNodeRegistered': function(aArea, aContainer) {
        //create your widget here
        if (aArea.id == targetAreaId) { //im not sure of the properties on aArea do a console.log('aArea properties:', aArea) to see what all properties are there
         createMyWidget();
        }
      }
    };
    CustomizableUI.addListener(myCustUiListener);
}
Другие вопросы по тегам