--- a/browser/modules/test/browser/browser_ProcessHangNotifications.js
+++ b/browser/modules/test/browser/browser_ProcessHangNotifications.js
@@ -38,30 +38,38 @@ const ADDON_HANG = 3;
const ADDON_ID = "fake-addon";
/**
* A mock nsIHangReport that we can pass through nsIObserverService
* to trigger notifications.
*
* @param hangType
* One of SLOW_SCRIPT, PLUGIN_HANG, ADDON_HANG.
+ * @param browser (optional)
+ * The <xul:browser> that this hang should be associated with.
+ * If not supplied, the hang will be associated with every browser,
+ * but the nsIHangReport.scriptBrowser attribute will return the
+ * currently selected browser in this window's gBrowser.
*/
-let TestHangReport = function(hangType = SLOW_SCRIPT) {
+let TestHangReport = function(hangType = SLOW_SCRIPT,
+ browser = gBrowser.selectedBrowser) {
this.promise = new Promise((resolve, reject) => {
this._resolver = resolve;
});
if (hangType == ADDON_HANG) {
// Add-on hangs are actually script hangs, but have an associated
// add-on ID for us to blame.
this._hangType = SLOW_SCRIPT;
this._addonId = ADDON_ID;
} else {
this._hangType = hangType;
}
+
+ this._browser = browser;
}
TestHangReport.prototype = {
SLOW_SCRIPT,
PLUGIN_HANG,
get addonId() {
return this._addonId;
@@ -90,17 +98,25 @@ TestHangReport.prototype = {
this._resolver(TEST_ACTION_TERMPLUGIN);
},
terminateGlobal() {
this._resolver(TEST_ACTION_TERMGLOBAL);
},
isReportForBrowser(aFrameLoader) {
+ if (this._browser) {
+ return this._browser.frameLoader === aFrameLoader;
+ }
+
return true;
+ },
+
+ get scriptBrowser() {
+ return this._browser;
}
};
// on dev edition we add a button for js debugging of hung scripts.
let buttonCount = (UpdateUtils.UpdateChannel == "aurora" ? 3 : 2);
add_task(async function setup() {
// Create a fake WebExtensionPolicy that we can use for
@@ -301,17 +317,17 @@ add_task(async function terminateAtShutd
/**
* Test that if there happens to be no open browser windows, that any
* hang reports that exist or appear while in this state will be handled
* automatically.
*/
add_task(async function terminateNoWindows() {
let testWin = await BrowserTestUtils.openNewBrowserWindow();
- let pausedHang = new TestHangReport(SLOW_SCRIPT);
+ let pausedHang = new TestHangReport(SLOW_SCRIPT, testWin.gBrowser.selectedBrowser);
Services.obs.notifyObservers(pausedHang, "process-hang-report");
ProcessHangMonitor.waitLonger(testWin);
ok(ProcessHangMonitor.findPausedReport(testWin.gBrowser.selectedBrowser),
"There should be a paused report for the selected browser.");
let pluginHang = new TestHangReport(PLUGIN_HANG);
let scriptHang = new TestHangReport(SLOW_SCRIPT);
let addonHang = new TestHangReport(ADDON_HANG);
@@ -365,8 +381,50 @@ add_task(async function terminateNoWindo
"With no open windows, should have terminated plugin for plugin hang.");
is(scriptAction2, TEST_ACTION_TERMSCRIPT,
"With no open windows, should have terminated script for script hang.");
is(addonAction2, TEST_ACTION_TERMGLOBAL,
"With no open windows, should have terminated global for add-on hang.");
document.documentElement.setAttribute("windowtype", "navigator:browser");
});
+
+/**
+ * Test that if a script hang occurs in one browser window, and that
+ * browser window goes away, that we clear the hang. For plug-in hangs,
+ * we do the conservative thing and terminate any plug-in hangs when a
+ * window closes, even though we don't exactly know which window it
+ * belongs to.
+ */
+add_task(async function terminateClosedWindow() {
+ let testWin = await BrowserTestUtils.openNewBrowserWindow();
+ let testBrowser = testWin.gBrowser.selectedBrowser;
+
+ let pausedHang = new TestHangReport(SLOW_SCRIPT, testBrowser);
+ Services.obs.notifyObservers(pausedHang, "process-hang-report");
+ ProcessHangMonitor.waitLonger(testWin);
+ ok(ProcessHangMonitor.findPausedReport(testWin.gBrowser.selectedBrowser),
+ "There should be a paused report for the selected browser.");
+
+ let pluginHang = new TestHangReport(PLUGIN_HANG, testBrowser);
+ let scriptHang = new TestHangReport(SLOW_SCRIPT, testBrowser);
+ let addonHang = new TestHangReport(ADDON_HANG, testBrowser);
+
+ [pluginHang, scriptHang, addonHang].forEach(hangReport => {
+ Services.obs.notifyObservers(hangReport, "process-hang-report");
+ });
+
+ await BrowserTestUtils.closeWindow(testWin);
+
+ let pausedAction = await pausedHang.promise;
+ let pluginAction = await pluginHang.promise;
+ let scriptAction = await scriptHang.promise;
+ let addonAction = await addonHang.promise;
+
+ is(pausedAction, TEST_ACTION_TERMSCRIPT,
+ "When closing window, should have terminated script for a paused script hang.");
+ is(pluginAction, TEST_ACTION_TERMPLUGIN,
+ "When closing window, should have terminated hung plug-in.");
+ is(scriptAction, TEST_ACTION_TERMSCRIPT,
+ "When closing window, should have terminated script for script hang.");
+ is(addonAction, TEST_ACTION_TERMGLOBAL,
+ "When closing window, should have terminated global for add-on hang.");
+});