import { ChromeLocalizationObserver } from '../../lib/observer/chrome';
import { XULLocalization } from '../../lib/dom/xul';

import { ChromeResourceBundle } from './io';
import { XULDocumentReady, getResourceLinks, createObserve } from './util';

Components.utils.import('resource://gre/modules/Services.jsm');
Components.utils.import('resource://gre/modules/L10nRegistry.jsm');
Components.utils.import('resource://gre/modules/IntlMessageContext.jsm');

const functions = {
  OS: function() {
    switch (Services.appinfo.OS) {
      case 'WINNT':
        return 'win';
      case 'Linux':
        return 'lin';
      case 'Darwin':
        return 'mac';
      case 'Android':
        return 'android';
      default:
        return 'other';
    }
  }
};

function createContext(lang) {
  return new MessageContext(lang, { functions });
}

document.l10n = new ChromeLocalizationObserver();
window.addEventListener('languagechange', document.l10n);

for (const [name, resIds] of getResourceLinks(document)) {
  if (!document.l10n.has(name)) {
    createLocalization(name, resIds);
  }
}

function createLocalization(name, resIds) {
  function requestBundles(requestedLangs = navigator.languages) {
    return L10nRegistry.getResources(requestedLangs, resIds).then(
      ({bundles}) => bundles.map(
        bundle => new ChromeResourceBundle(bundle.locale, bundle.resources)
      )
    );
  }

  const l10n = new XULLocalization(requestBundles, createContext);
  l10n.observe = createObserve(document.l10n);

  window.addEventListener('load', () => {
    Services.obs.addObserver(l10n, 'language-registry-update', false);
    Services.obs.addObserver(l10n, 'language-registry-incremental', false);
  });

  window.addEventListener('unload', () => {
    Services.obs.removeObserver(l10n, 'language-registry-update');
    Services.obs.removeObserver(l10n, 'language-registry-incremental');
  });

  document.l10n.set(name, l10n);

  if (name === 'main') {
    XULDocumentReady().then(() => {
      const rootElem = document.documentElement;
      document.l10n.observeRoot(rootElem, l10n);
      document.l10n.translateRoot(rootElem, l10n);
    });
  }
}

@@ -448,16 +448,248 @@
 jsm');%0A%0A
+// List of functions passed to %60MessageContext%60 that will be available%0A// from within the localization entities.%0A//%0A// Example use (in FTL):%0A//%0A// open-settings = %7BOS() -%3E%0A//   %5Bmac%5D Open Preferences%0A//  *%5Bother%5D Open Settings%0A// %7D%0A
 const fu
@@ -986,200 +986,675 @@
 %7D;%0A%0A
-function createContext(lang) %7B%0A  return new MessageContext(lang, %7B functions %7D);%0A%7D%0A%0Adocument.l10n = new ChromeLocalizationObserver();%0Awindow.addEventListener('languagechange', document.l10n);%0A
+// This function is provided to the constructor of %60Localization%60 object%0A// and is used to create new %60MessageContext%60 objects for a given %60lang%60%0A// with selected builtin functions.%0A%0Afunction createContext(lang) %7B%0A  return new MessageContext(lang, %7B functions %7D);%0A%7D%0A%0A// This is the initial running code of l20n.js%0A// We create a new  %60ChromeLocalizationObserver%60 and define an event%0A// listener for %60languagechange%60 on it.%0Adocument.l10n = new ChromeLocalizationObserver();%0Awindow.addEventListener('languagechange', document.l10n);%0A%0A// Next, we collect all l10n resource links, create new %60Localization%60%0A// objects and bind them to the %60LocalizationObserver%60 instance.
 %0Afor
@@ -1832,16 +1832,178 @@
 sIds) %7B%0A
+  // This function is called by %60Localization%60 class to%0A  // retrieve %60ResourceBundle%60.%0A  //%0A  // In chrome-privileged setup we're using %60L10nRegistry%60 for that.%0A
   functi
@@ -2328,55 +2328,265 @@
 t);%0A
-  l10n.observe = createObserve(document.l10n);%0A
+%0A  // This creates nsIObserver's observe method bound to %60LocalizationObserver%60%0A  l10n.observe = createObserve(document.l10n);%0A%0A  // This adds observer handlers on our custom events that will%0A  // be triggered when L10nRegistry notifies on resource updates.
 %0A  w
@@ -3023,24 +3023,138 @@
 = 'main') %7B%0A
+    // When document is ready, we trigger it's localization and%0A    // initialize %60MutationObserver%60 on the root.%0A
     XULDocum

Document l20n-chrome-xul