Bug 1355354 - Keep a reference to the progress listener to keep it from being gc'ed prematurely. r?mossop draft
authorBrendan Dahl <brendan.dahl@gmail.com>
Tue, 16 Jan 2018 11:26:40 -0800
changeset 721144 496fce68b6df4cbe2aea5e19696b87b6b9272481
parent 721137 0bc627ade5a07e236365c649b9be3b525c156988
child 746240 5590b97cb42367fb02c1913c48f8c24a76c537d0
push id95738
push userbmo:bdahl@mozilla.com
push dateTue, 16 Jan 2018 19:31:22 +0000
reviewersmossop
bugs1355354
milestone59.0
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);