Bug 708397 - "addon-options-displayed" notification fires before XBL bindings apply; r=Unfocused, a=Unfocused
authorGeoff Lankow <geoff@darktrojan.net>
Tue, 13 Dec 2011 23:32:11 +1300
changeset 84113 4b71b1e9cc0c30b13ee67d71d4030b6754ab0e38
parent 84112 3c321d2c988400e34a77bc355bc404c1f7b55d13
child 84114 b2c3fd1b871b0edf25c053054c276cec0d61e33d
push id519
push userakeybl@mozilla.com
push dateWed, 01 Feb 2012 00:38:35 +0000
treeherdermozilla-beta@788ea1ef610b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersUnfocused, Unfocused
bugs708397
milestone11.0a1
first release with
nightly win64
4b71b1e9cc0c / 11.0a1 / 20111213031157 / files
nightly linux32
nightly linux64
nightly mac
nightly win32
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly win64
Bug 708397 - "addon-options-displayed" notification fires before XBL bindings apply; r=Unfocused, a=Unfocused
toolkit/mozapps/extensions/content/extensions.js
toolkit/mozapps/extensions/test/browser/browser_inlinesettings.js
--- a/toolkit/mozapps/extensions/content/extensions.js
+++ b/toolkit/mozapps/extensions/content/extensions.js
@@ -2876,52 +2876,66 @@ var gDetailView = {
 
     var xhr = new XMLHttpRequest();
     xhr.open("GET", this._addon.optionsURL, false);
     xhr.send();
 
     var xml = xhr.responseXML;
     var settings = xml.querySelectorAll(":root > setting");
 
-    for (var i = 0, first = true; i < settings.length; i++) {
+    var firstSetting = null;
+    for (var i = 0; i < settings.length; i++) {
       var setting = settings[i];
 
       // Remove setting description, for replacement later
       var desc = stripTextNodes(setting).trim();
       if (setting.hasAttribute("desc")) {
         desc = setting.getAttribute("desc").trim();
         setting.removeAttribute("desc");
       }
 
       var type = setting.getAttribute("type");
       if (type == "file" || type == "directory")
         setting.setAttribute("fullpath", "true");
 
       rows.appendChild(setting);
       var visible = window.getComputedStyle(setting, null).getPropertyValue("display") != "none";
-      if (first && visible) {
+      if (!firstSetting && visible) {
         setting.setAttribute("first-row", true);
-        first = false;
+        firstSetting = setting;
       }
 
       // Add a new row containing the description
       if (desc) {
         var row = document.createElement("row");
         if (!visible) {
           row.setAttribute("unsupported", "true");
         }
         var label = document.createElement("label");
         label.className = "preferences-description";
         label.textContent = desc;
         row.appendChild(label);
         rows.appendChild(row);
       }
     }
 
-    Services.obs.notifyObservers(document, "addon-options-displayed", this._addon.id);
+	// Ensure the page has loaded and force the XBL bindings to be synchronously applied,
+	// then notify observers.
+    if (gViewController.viewPort.selectedPanel.hasAttribute("loading")) {
+      gDetailView.node.addEventListener("ViewChanged", function viewChangedEventListener() {
+        gDetailView.node.removeEventListener("ViewChanged", viewChangedEventListener, false);
+        if (firstSetting)
+          firstSetting.clientTop;
+        Services.obs.notifyObservers(document, "addon-options-displayed", gDetailView._addon.id);
+      }, false);
+    } else {
+      if (firstSetting)
+        firstSetting.clientTop;
+      Services.obs.notifyObservers(document, "addon-options-displayed", this._addon.id);
+    }
   },
 
   getSelectedAddon: function() {
     return this._addon;
   },
 
   onEnabling: function() {
     this.updateState();
--- a/toolkit/mozapps/extensions/test/browser/browser_inlinesettings.js
+++ b/toolkit/mozapps/extensions/test/browser/browser_inlinesettings.js
@@ -11,18 +11,24 @@ var gProvider;
 const SETTINGS_ROWS = 8;
 
 var MockFilePicker = SpecialPowers.MockFilePicker;
 MockFilePicker.reset();
 
 var observer = {
   lastData: null,
   observe: function(aSubject, aTopic, aData) {
-    if (aTopic == "addon-options-displayed")
+    if (aTopic == "addon-options-displayed") {
       this.lastData = aData;
+      // Test if the binding has applied before the observers are notified. We test the second setting here,
+      // because the code operates on the first setting and we want to check it applies to all.
+      var setting = aSubject.querySelector("rows > setting[first-row] ~ setting");
+      var input = gManagerWindow.document.getAnonymousElementByAttribute(setting, "class", "setting-label");
+      isnot(input, null, "XBL binding should be applied");
+    }
   }
 };
 
 function installAddon(aCallback) {
   AddonManager.getInstallForURL(TESTROOT + "addons/browser_inlinesettings1.xpi",
                                 function(aInstall) {
     aInstall.addListener({
       onInstallEnded: function() {
@@ -458,21 +464,25 @@ add_test(function() {
 
       button = gManagerWindow.document.getAnonymousElementByAttribute(addon, "anonid", "details-btn");
       EventUtils.synthesizeMouseAtCenter(button, { clickCount: 1 }, gManagerWindow);
 
       wait_for_view_load(gManagerWindow, function() {
         var grid = gManagerWindow.document.getElementById("detail-grid");
         var settings = grid.querySelectorAll("rows > setting");
         is(settings.length, 0, "Grid should not have settings children");
+        
+        observer.lastData = null;
 
         // enable
         var button = gManagerWindow.document.getElementById("detail-enable-btn");
         EventUtils.synthesizeMouseAtCenter(button, { clickCount: 1 }, gManagerWindow);
 
+        is(observer.lastData, "inlinesettings1@tests.mozilla.org", "Observer notification should have fired");
+
         settings = grid.querySelectorAll("rows > setting");
         is(settings.length, SETTINGS_ROWS, "Grid should have settings children");
 
         gCategoryUtilities.openType("extension", run_next_test);
       });
     });
   });
 });