Bug 632290: Intermittent browser_about.js timeout. r=Mossop
authorIrving Reid <irving@cfrq.net>
Thu, 18 Dec 2014 11:42:26 -0800
changeset 246204 83689aa1a00fadd691f40fd999b3ce16304b2af8
parent 246203 4f4c2f1108cca2c27275f04452f95a2251d77a68
child 246205 08d1470a4042964793d541dd3fc0a0264fec60ec
push id4489
push userraliiev@mozilla.com
push dateMon, 23 Feb 2015 15:17:55 +0000
treeherdermozilla-beta@fd7c3dc24146 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersMossop
bugs632290
milestone37.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 632290: Intermittent browser_about.js timeout. r=Mossop
toolkit/mozapps/extensions/test/browser/browser_about.js
--- a/toolkit/mozapps/extensions/test/browser/browser_about.js
+++ b/toolkit/mozapps/extensions/test/browser/browser_about.js
@@ -9,76 +9,86 @@
  * Addon object not passed to custom about dialogs.
  */
 
 var gManagerWindow;
 
 const URI_ABOUT_DEFAULT = "chrome://mozapps/content/extensions/about.xul";
 const URI_ABOUT_CUSTOM = CHROMEROOT + "addon_about.xul";
 
-function test() {
-  requestLongerTimeout(2);
-
-  waitForExplicitFinish();
-
+ add_task(function* test() {
   var gProvider = new MockProvider();
   gProvider.createAddons([{
     id: "test1@tests.mozilla.org",
     name: "Test add-on 1",
     description: "foo"
   },
   {
     id: "test2@tests.mozilla.org",
     name: "Test add-on 2",
     description: "bar",
     aboutURL: URI_ABOUT_CUSTOM
   }]);
 
-  open_manager("addons://list/extension", function(aManager) {
-    gManagerWindow = aManager;
+  gManagerWindow = yield open_manager("addons://list/extension");
+
+  yield test_about_window("Test add-on 1", URI_ABOUT_DEFAULT);
+  yield test_about_window("Test add-on 2", URI_ABOUT_CUSTOM);
+  yield close_manager(gManagerWindow);
+});
+
+function test_about_window(aAddonItemName, aExpectedAboutUri) {
+  return new Promise((resolve, reject) => {
+    let addonList = gManagerWindow.document.getElementById("addon-list");
+    let selectedItem = null;
+
+    for (let addonItem of addonList.childNodes) {
+      if (addonItem.hasAttribute("name") &&
+          addonItem.getAttribute("name") === aAddonItemName) {
+        selectedItem = addonItem;
+        break;
+      }
+    }
+    ok(selectedItem, "Found addon item for " + aAddonItemName);
+
+    info("Waiting for about dialog");
+    // This gets notified inside a modal dialog that spins the event loop, so we're
+    // stuck with callbacks rather than Task/Promise.
+    Services.ww.registerNotification(function TEST_ww_observer(aSubject, aTopic,
+                                                               aData) {
+      if (aTopic == "domwindowclosed") {
+        Services.ww.unregisterNotification(TEST_ww_observer);
 
-    test_about_window("Test add-on 1", URI_ABOUT_DEFAULT, function() {
-      test_about_window("Test add-on 2", URI_ABOUT_CUSTOM, function() {
-        close_manager(gManagerWindow, finish);
-      });
+        info("About dialog closing, waiting for focus on browser window");
+      } else if (aTopic == "domwindowopened") {
+        // Always let the stack unwind...
+        executeSoon(() => {
+          info("About dialog opened, waiting for focus");
+
+          let win = aSubject.QueryInterface(Ci.nsIDOMEventTarget);
+          waitForFocus(function() {
+            info("Saw about dialog");
+
+            is(win.location,
+               aExpectedAboutUri,
+               "The correct add-on about window should have opened");
+
+            is(win.arguments && win.arguments[0] && win.arguments[0].name,
+               aAddonItemName,
+               "window.arguments[0] should refer to the add-on object");
+
+            win.close();
+          }, win);
+        });
+      } else {
+        info("Got window notification " + aTopic);
+      }
     });
+
+    // This opens a modal dialog, so the main execution thread doesn't get control
+    // (and the event loop spins under us) until the WindowWatcher domwindowopened
+    // callback closes it.
+    gManagerWindow.gViewController.doCommand("cmd_showItemAbout",
+                                             selectedItem.mAddon);
+    // wait for focus back on manager window
+    waitForFocus(resolve);
   });
 }
-
-function test_about_window(aAddonItemName, aExpectedAboutUri, aCallback) {
-  var addonList = gManagerWindow.document.getElementById("addon-list");
-  for (var addonItem of addonList.childNodes) {
-    if (addonItem.hasAttribute("name") &&
-        addonItem.getAttribute("name") === aAddonItemName)
-      break;
-  }
-
-  info("Waiting for about dialog");
-  Services.ww.registerNotification(function TEST_ww_observer(aSubject, aTopic,
-                                                             aData) {
-    if (aTopic == "domwindowclosed") {
-      Services.ww.unregisterNotification(TEST_ww_observer);
-
-      info("About dialog closed, waiting for focus on browser window");
-      waitForFocus(() => executeSoon(aCallback));
-    } else if (aTopic == "domwindowopened") {
-      info("About dialog opened, waiting for focus");
-
-      let win = aSubject.QueryInterface(Ci.nsIDOMEventTarget);
-      waitForFocus(function() {
-        info("Saw about dialog");
-
-        is(win.location,
-           aExpectedAboutUri,
-           "The correct add-on about window should have opened");
-
-        is(win.arguments && win.arguments[0] && win.arguments[0].name,
-           aAddonItemName,
-           "window.arguments[0] should refer to the add-on object");
-
-        executeSoon(() => win.close());
-      }, win);
-    }
-  });
-
-  gManagerWindow.gViewController.doCommand("cmd_showItemAbout",
-                                           addonItem.mAddon);
-}