Bug 1147720 - Fix intermittent waitForDocLoadAndStopIt() timeouts by keeping a strong reference to the progress listener r=mak
authorTim Taubert <ttaubert@mozilla.com>
Thu, 26 Mar 2015 11:38:10 +0100
changeset 264712 c3f447e3cf58ea08a0730a51c9f300e0c6f32ed6
parent 264711 250512664b2130146b0ec4319996e3a968749232
child 264713 6306a0c0be6597610bffb95a4eac68931f886d5d
push id4718
push userraliiev@mozilla.com
push dateMon, 11 May 2015 18:39:53 +0000
treeherdermozilla-beta@c20c4ef55f08 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmak
bugs1147720
milestone39.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 1147720 - Fix intermittent waitForDocLoadAndStopIt() timeouts by keeping a strong reference to the progress listener r=mak
browser/base/content/test/general/browser_urlbarStop.js
browser/base/content/test/general/head.js
--- a/browser/base/content/test/general/browser_urlbarStop.js
+++ b/browser/base/content/test/general/browser_urlbarStop.js
@@ -20,50 +20,12 @@ add_task(function* () {
   gBrowser.removeCurrentTab();
 });
 
 function typeAndSubmitAndStop(url) {
   gBrowser.userTypedValue = url;
   URLBarSetURI();
   is(gURLBar.textValue, gURLBar.trimValue(url), "location bar reflects loading page");
 
-  let promise = waitForDocLoadAndStopIt();
+  let promise = waitForDocLoadAndStopIt(url);
   gURLBar.handleCommand();
   return promise;
 }
-
-function waitForDocLoadAndStopIt() {
-  function content_script() {
-    const {interfaces: Ci, utils: Cu} = Components;
-    Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-
-    let progressListener = {
-      onStateChange(webProgress, req, flags, status) {
-        if (flags & Ci.nsIWebProgressListener.STATE_START) {
-          wp.removeProgressListener(progressListener);
-
-          /* Hammer time. */
-          content.stop();
-
-          /* Let the parent know we're done. */
-          sendAsyncMessage("{MSG}");
-        }
-      },
-
-      QueryInterface: XPCOMUtils.generateQI(["nsISupportsWeakReference"])
-    };
-
-    let wp = docShell.QueryInterface(Ci.nsIWebProgress);
-    wp.addProgressListener(progressListener, wp.NOTIFY_ALL);
-  }
-
-  return new Promise(resolve => {
-    const MSG = "test:waitForDocLoadAndStopIt";
-    const SCRIPT = content_script.toString().replace("{MSG}", MSG);
-
-    let mm = gBrowser.selectedBrowser.messageManager;
-    mm.loadFrameScript("data:,(" + SCRIPT + ")();", true);
-    mm.addMessageListener(MSG, function onComplete() {
-      mm.removeMessageListener(MSG, onComplete);
-      resolve();
-    });
-  });
-}
--- a/browser/base/content/test/general/head.js
+++ b/browser/base/content/test/general/head.js
@@ -374,29 +374,45 @@ function waitForDocLoadAndStopIt(aExpect
   function content_script() {
     let { interfaces: Ci, utils: Cu } = Components;
     Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
     let wp = docShell.QueryInterface(Ci.nsIWebProgress);
 
     let progressListener = {
       onStateChange: function (webProgress, req, flags, status) {
         dump("waitForDocLoadAndStopIt: onStateChange " + flags.toString(16) + ": " + req.name + "\n");
-        let docStart = Ci.nsIWebProgressListener.STATE_IS_DOCUMENT |
-                       Ci.nsIWebProgressListener.STATE_START;
-        if (((flags & docStart) == docStart) && webProgress.isTopLevel) {
-          dump("waitForDocLoadAndStopIt: Document start: " +
-               req.QueryInterface(Ci.nsIChannel).URI.spec + "\n");
-          req.cancel(Components.results.NS_ERROR_FAILURE);
+
+        if (webProgress.isTopLevel &&
+            flags & Ci.nsIWebProgressListener.STATE_START) {
           wp.removeProgressListener(progressListener);
-          sendAsyncMessage("Test:WaitForDocLoadAndStopIt", { uri: req.originalURI.spec });
+
+          let chan = req.QueryInterface(Ci.nsIChannel);
+          dump(`waitForDocLoadAndStopIt: Document start: ${chan.URI.spec}\n`);
+
+          /* Hammer time. */
+          content.stop();
+
+          /* Let the parent know we're done. */
+          sendAsyncMessage("Test:WaitForDocLoadAndStopIt", { uri: chan.originalURI.spec });
         }
       },
       QueryInterface: XPCOMUtils.generateQI(["nsISupportsWeakReference"])
     };
-    wp.addProgressListener(progressListener, wp.NOTIFY_ALL);
+    wp.addProgressListener(progressListener, wp.NOTIFY_STATE_WINDOW);
+
+    /**
+     * As |this| is undefined and we can't extend |docShell|, adding an unload
+     * event handler is the easiest way to ensure the weakly referenced
+     * progress listener is kept alive as long as necessary.
+     */
+    addEventListener("unload", function () {
+      try {
+        wp.removeProgressListener(progressListener);
+      } catch (e) { /* Will most likely fail. */ }
+    });
   }
 
   return new Promise((resolve, reject) => {
     function complete({ data }) {
       is(data.uri, aExpectedURL, "waitForDocLoadAndStopIt: The expected URL was loaded");
       mm.removeMessageListener("Test:WaitForDocLoadAndStopIt", complete);
       resolve();
     }