Bug 1391594 - If a window closes while hosting a <xul:browser> hung on script, clear the hang. r?billm draft
authorMike Conley <mconley@mozilla.com>
Fri, 13 Oct 2017 16:15:44 -0400
changeset 682843 7d138e2aef65a9ce97220893951fdc9116eaf2b5
parent 682773 5e5733884c26d3e854bf1e1b36cf38aa54267731
child 682844 64a1ec0f8fdff8482ad10e938ac786d024cc8c96
push id85178
push usermconley@mozilla.com
push dateWed, 18 Oct 2017 21:08:28 +0000
reviewersbillm
bugs1391594
milestone58.0a1
Bug 1391594 - If a window closes while hosting a <xul:browser> hung on script, clear the hang. r?billm MozReview-Commit-ID: 88oj1bqA9To
browser/modules/ProcessHangMonitor.jsm
--- a/browser/modules/ProcessHangMonitor.jsm
+++ b/browser/modules/ProcessHangMonitor.jsm
@@ -250,31 +250,79 @@ var ProcessHangMonitor = {
         let win = subject.QueryInterface(Ci.nsIDOMWindow);
         let listener = (ev) => {
           win.removeEventListener("load", listener, true);
           this.updateWindows();
         };
         win.addEventListener("load", listener, true);
         break;
       }
+
+      case "domwindowclosed": {
+        let win = subject.QueryInterface(Ci.nsIDOMWindow);
+        this.onWindowClosed(win);
+        break;
+      }
     }
   },
 
   /**
    * Called early on in the shutdown sequence. We take this opportunity to
    * take any pre-existing hang reports, and terminate them. We also put
    * ourselves in a state so that if any more hang reports show up while
    * we're shutting down, we terminate them immediately.
    */
   onQuitApplicationGranted() {
     this._shuttingDown = true;
     this.stopAllHangs();
     this.updateWindows();
   },
 
+  onWindowClosed(win) {
+    let maybeStopHang = (report) => {
+      if (report.hangType == report.SLOW_SCRIPT) {
+        let hungBrowserWindow = null;
+        try {
+          hungBrowserWindow = report.scriptBrowser.ownerGlobal;
+        } catch (e) {
+          // Ignore failures to get the script browser - we'll be
+          // conservative, and assume that if we cannot access the
+          // window that belongs to this report that we should stop
+          // the hang.
+        }
+        if (!hungBrowserWindow || hungBrowserWindow == win) {
+          this.stopHang(report);
+          return true;
+        }
+      } else if (report.hangType == report.PLUGIN_HANG) {
+        // If any window has closed during a plug-in hang, we'll
+        // do the conservative thing and terminate the plug-in.
+        this.stopHang(report);
+        return true;
+      }
+      return false;
+    }
+
+    // If there are any script hangs for browsers that are in this window
+    // that is closing, we can stop them now.
+    for (let report of this._activeReports) {
+      if (maybeStopHang(report)) {
+        this._activeReports.delete(report);
+      }
+    }
+
+    for (let [pausedReport, ] of this._pausedReports) {
+      if (maybeStopHang(pausedReport)) {
+        this.removePausedReport(pausedReport);
+      }
+    }
+
+    this.updateWindows();
+  },
+
   stopAllHangs() {
     for (let report of this._activeReports) {
       this.stopHang(report);
     }
 
     this._activeReports = new Set();
 
     for (let [pausedReport, ] of this._pausedReports) {