Bug 1355354 - Keep a reference to the progress listener to keep it from being gc'ed prematurely. r=mossop
authorBrendan Dahl <brendan.dahl@gmail.com>
Tue, 16 Jan 2018 11:26:40 -0800
changeset 454041 ff483bbeacaf72aff8e6ec6e227dafdcdce11825
parent 454040 921fc0797dc1ef65d17da35af667d64419cd947d
child 454042 f924db10f84f5b10536651002965ebcefb3b8a72
push id1648
push usermtabara@mozilla.com
push dateThu, 01 Mar 2018 12:45:47 +0000
treeherdermozilla-release@cbb9688c2eeb [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmossop
bugs1355354
milestone59.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 1355354 - Keep a reference to the progress listener to keep it from being gc'ed prematurely. r=mossop MozReview-Commit-ID: A6WM1Bj3Z5L
browser/components/shell/HeadlessShell.jsm
widget/headless/tests/test_headless.js
--- a/browser/components/shell/HeadlessShell.jsm
+++ b/browser/components/shell/HeadlessShell.jsm
@@ -7,16 +7,20 @@
 let EXPORTED_SYMBOLS = ["HeadlessShell"];
 
 Components.utils.import("resource://gre/modules/Services.jsm");
 Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
 Components.utils.import("resource://gre/modules/osfile.jsm");
 
 const Ci = Components.interfaces;
 
+// Refrences to the progress listeners to keep them from being gc'ed
+// before they are called.
+const progressListeners = new Map();
+
 function loadContentWindow(webNavigation, uri) {
   return new Promise((resolve, reject) => {
     webNavigation.loadURI(uri, Ci.nsIWebNavigation.LOAD_FLAGS_NONE, null, null, null);
     let docShell = webNavigation.QueryInterface(Ci.nsIInterfaceRequestor)
                                 .getInterface(Ci.nsIDocShell);
     let webProgress = docShell.QueryInterface(Ci.nsIInterfaceRequestor)
                               .getInterface(Ci.nsIWebProgress);
     let progressListener = {
@@ -26,24 +30,26 @@ function loadContentWindow(webNavigation
           return;
         }
         // Ignore events that don't change the document
         if (flags & Ci.nsIWebProgressListener.LOCATION_CHANGE_SAME_DOCUMENT) {
           return;
         }
         let contentWindow = docShell.QueryInterface(Ci.nsIInterfaceRequestor)
                                     .getInterface(Ci.nsIDOMWindow);
+        progressListeners.delete(progressListener);
         webProgress.removeProgressListener(progressListener);
         contentWindow.addEventListener("load", (event) => {
           resolve(contentWindow);
         }, { once: true });
       },
       QueryInterface: XPCOMUtils.generateQI(["nsIWebProgressListener",
                                              "nsISupportsWeakReference"])
     };
+    progressListeners.set(progressListener, progressListener);
     webProgress.addProgressListener(progressListener,
                                     Ci.nsIWebProgress.NOTIFY_LOCATION);
   });
 }
 
 async function takeScreenshot(fullWidth, fullHeight, contentWidth, contentHeight, path, url) {
   try {
     let windowlessBrowser = Services.appShell.createWindowlessBrowser(false);
--- a/widget/headless/tests/test_headless.js
+++ b/widget/headless/tests/test_headless.js
@@ -10,16 +10,20 @@ const server = new HttpServer();
 server.registerDirectory("/", do_get_cwd());
 server.start(-1);
 const ROOT = `http://localhost:${server.identity.primaryPort}`;
 const BASE = `${ROOT}/`;
 const HEADLESS_URL = `${BASE}/headless.html`;
 const HEADLESS_BUTTON_URL = `${BASE}/headless_button.html`;
 registerCleanupFunction(() => { server.stop(() => {})});
 
+// Refrences to the progress listeners to keep them from being gc'ed
+// before they are called.
+const progressListeners = new Map();
+
 function loadContentWindow(webNavigation, uri) {
   return new Promise((resolve, reject) => {
     webNavigation.loadURI(uri, Ci.nsIWebNavigation.LOAD_FLAGS_NONE, null, null, null);
     let docShell = webNavigation.QueryInterface(Ci.nsIInterfaceRequestor)
                   .getInterface(Ci.nsIDocShell);
     let webProgress = docShell.QueryInterface(Ci.nsIInterfaceRequestor)
                       .getInterface(Ci.nsIWebProgress);
     let progressListener = {
@@ -32,23 +36,25 @@ function loadContentWindow(webNavigation
         if (flags & Ci.nsIWebProgressListener.LOCATION_CHANGE_SAME_DOCUMENT) {
           return;
         }
         let docShell = webNavigation.QueryInterface(Ci.nsIInterfaceRequestor)
                        .getInterface(Ci.nsIDocShell);
         let contentWindow = docShell.QueryInterface(Ci.nsIInterfaceRequestor)
                             .getInterface(Ci.nsIDOMWindow);
         webProgress.removeProgressListener(progressListener);
+        progressListeners.delete(progressListener);
         contentWindow.addEventListener("load", (event) => {
           resolve(contentWindow);
         }, { once: true });
       },
       QueryInterface: XPCOMUtils.generateQI(["nsIWebProgressListener",
                                             "nsISupportsWeakReference"])
     };
+    progressListeners.set(progressListener, progressListener);
     webProgress.addProgressListener(progressListener,
                                     Ci.nsIWebProgress.NOTIFY_LOCATION);
   });
 }
 
 add_task(async function test_snapshot() {
   let windowlessBrowser = Services.appShell.createWindowlessBrowser(false);
   let webNavigation = windowlessBrowser.QueryInterface(Ci.nsIWebNavigation);