diff --git a/browser/devtools/webconsole/HUDService-content.js b/browser/devtools/webconsole/HUDService-content.js index 8361e71c8cf..b558f2798c6 100644 --- a/browser/devtools/webconsole/HUDService-content.js +++ b/browser/devtools/webconsole/HUDService-content.js @@ -7,31 +7,25 @@ "use strict"; // This code is appended to the browser content script. -(function(_global) { -const Cc = Components.classes; -const Ci = Components.interfaces; -const Cu = Components.utils; +(function _HUDServiceContent() { +let Cc = Components.classes; +let Ci = Components.interfaces; +let Cu = Components.utils; -Cu.import("resource://gre/modules/XPCOMUtils.jsm"); -Cu.import("resource://gre/modules/Services.jsm"); +let tempScope = {}; +Cu.import("resource://gre/modules/XPCOMUtils.jsm", tempScope); +Cu.import("resource://gre/modules/Services.jsm", tempScope); +Cu.import("resource://gre/modules/ConsoleAPIStorage.jsm", tempScope); +Cu.import("resource:///modules/WebConsoleUtils.jsm", tempScope); -XPCOMUtils.defineLazyGetter(_global, "gConsoleStorage", function () { - let obj = {}; - Cu.import("resource://gre/modules/ConsoleAPIStorage.jsm", obj); - return obj.ConsoleAPIStorage; -}); +let XPCOMUtils = tempScope.XPCOMUtils; +let Services = tempScope.Services; +let gConsoleStorage = tempScope.ConsoleAPIStorage; +let WebConsoleUtils = tempScope.WebConsoleUtils; +let l10n = WebConsoleUtils.l10n; +tempScope = null; -XPCOMUtils.defineLazyGetter(_global, "WebConsoleUtils", function () { - let obj = {}; - Cu.import("resource:///modules/WebConsoleUtils.jsm", obj); - return obj.WebConsoleUtils; -}); - -XPCOMUtils.defineLazyGetter(_global, "l10n", function () { - return WebConsoleUtils.l10n; -}); - -_global = null; +let _alive = true; // Track if this content script should still be alive. /** * The Web Console content instance manager. @@ -63,6 +57,26 @@ let Manager = { this._messageListeners.forEach(function(aName) { addMessageListener(aName, this); }, this); + + // Need to track the owner XUL window to listen to the unload and TabClose + // events, to avoid memory leaks. + let xulWindow = this.window.QueryInterface(Ci.nsIInterfaceRequestor) + .getInterface(Ci.nsIWebNavigation) + .QueryInterface(Ci.nsIDocShell) + .chromeEventHandler.ownerDocument.defaultView; + + xulWindow.addEventListener("unload", this._onXULWindowClose, false); + + let tabContainer = xulWindow.gBrowser.tabContainer; + tabContainer.addEventListener("TabClose", this._onTabClose, false); + + // Need to track private browsing change and quit application notifications, + // again to avoid memory leaks. The Web Console main process cannot notify + // this content script when the XUL window close, tab close, private + // browsing change and quit application events happen, so we must call + // Manager.destroy() on our own. + Services.obs.addObserver(this, "private-browsing-change-granted", false); + Services.obs.addObserver(this, "quit-application-granted", false); }, /** @@ -71,6 +85,10 @@ let Manager = { */ receiveMessage: function Manager_receiveMessage(aMessage) { + if (!_alive) { + return; + } + if (!aMessage.json || (aMessage.name != "WebConsole:Init" && aMessage.json.hudId != this.hudId)) { Cu.reportError("Web Console content script: received message " + @@ -99,6 +117,22 @@ let Manager = { } }, + /** + * Observe notifications from the nsIObserverService. + * + * @param mixed aSubject + * @param string aTopic + * @param mixed aData + */ + observe: function Manager_observe(aSubject, aTopic, aData) + { + if (_alive && (aTopic == "quit-application-granted" || + (aTopic == "private-browsing-change-granted" && + (aData == "enter" || aData == "exit")))) { + this.destroy(); + } + }, + /** * The manager initialization code. This method is called when the Web Console * remote process initializes the content process (this code!). @@ -110,9 +144,11 @@ let Manager = { * - features - (optional) array of features you want to enable from * the start. For each feature you enable you can pass feature-specific * options in a property on the JSON object you send with the same name - * as the feature. + * as the feature. See this.enableFeature() for the list of available + * features. * - cachedMessages - (optional) an array of cached messages you want - * to receive: only "ConsoleAPI" is available for now. + * to receive. See this._sendCachedMessages() for the list of available + * message types. * * Example message: * { @@ -203,6 +239,8 @@ let Manager = { * - JSTerm - a JavaScript "terminal" which allows code execution. * - ConsoleAPI - support for routing the window.console API to the remote * process. + * - PageError - route all the nsIScriptErrors from the nsIConsoleService + * to the remote process. * * @param string aFeature * One of the supported features: JSTerm, ConsoleAPI. @@ -223,6 +261,9 @@ let Manager = { case "ConsoleAPI": ConsoleAPIObserver.init(aMessage); break; + case "PageError": + ConsoleListener.init(aMessage); + break; default: Cu.reportError("Web Console content: unknown feature " + aFeature); break; @@ -236,7 +277,8 @@ let Manager = { * * @see this.enableFeature * @param string aFeature - * One of the supported features: JSTerm, ConsoleAPI. + * One of the supported features - see this.enableFeature() for the + * list of supported features. */ disableFeature: function Manager_disableFeature(aFeature) { @@ -253,6 +295,9 @@ let Manager = { case "ConsoleAPI": ConsoleAPIObserver.destroy(); break; + case "PageError": + ConsoleListener.destroy(); + break; default: Cu.reportError("Web Console content: unknown feature " + aFeature); break; @@ -264,17 +309,22 @@ let Manager = { * * @private * @param array aMessageTypes - * An array that lists which kinds of messages you want. Currently only - * "ConsoleAPI" messages are supported. + * An array that lists which kinds of messages you want. Supported + * message types: "ConsoleAPI" and "PageError". */ _sendCachedMessages: function Manager__sendCachedMessages(aMessageTypes) { let messages = []; - switch (aMessageTypes.shift()) { - case "ConsoleAPI": - messages.push.apply(messages, ConsoleAPIObserver.getCachedMessages()); - break; + while (aMessageTypes.length > 0) { + switch (aMessageTypes.shift()) { + case "ConsoleAPI": + messages.push.apply(messages, ConsoleAPIObserver.getCachedMessages()); + break; + case "PageError": + messages.push.apply(messages, ConsoleListener.getCachedMessages()); + break; + } } messages.sort(function(a, b) { return a.timeStamp - b.timeStamp; }); @@ -282,11 +332,49 @@ let Manager = { this.sendMessage("WebConsole:CachedMessages", {messages: messages}); }, + /** + * The XUL window "unload" event handler which destroys this content script + * instance. + * @private + */ + _onXULWindowClose: function Manager__onXULWindowClose() + { + if (_alive) { + Manager.destroy(); + } + }, + + /** + * The "TabClose" event handler which destroys this content script + * instance, if needed. + * @private + */ + _onTabClose: function Manager__onTabClose(aEvent) + { + let tab = aEvent.target; + if (_alive && tab.linkedBrowser.contentWindow === Manager.window) { + Manager.destroy(); + } + }, + /** * Destroy the Web Console content script instance. */ destroy: function Manager_destroy() { + Services.obs.removeObserver(this, "private-browsing-change-granted"); + Services.obs.removeObserver(this, "quit-application-granted"); + + _alive = false; + let xulWindow = this.window.QueryInterface(Ci.nsIInterfaceRequestor) + .getInterface(Ci.nsIWebNavigation) + .QueryInterface(Ci.nsIDocShell) + .chromeEventHandler.ownerDocument.defaultView; + + xulWindow.removeEventListener("unload", this._onXULWindowClose, false); + let tabContainer = xulWindow.gBrowser.tabContainer; + tabContainer.removeEventListener("TabClose", this._onTabClose, false); + this._messageListeners.forEach(function(aName) { removeMessageListener(aName, this); }, this); @@ -295,7 +383,9 @@ let Manager = { this.hudId = null; this._messageHandlers = null; - Manager = ConsoleAPIObserver = JSTerm = null; + Manager = ConsoleAPIObserver = JSTerm = ConsoleListener = null; + Cc = Ci = Cu = XPCOMUtils = Services = gConsoleStorage = + WebConsoleUtils = l10n = null; }, }; @@ -447,7 +537,7 @@ let ConsoleAPIObserver = { */ observe: function CAO_observe(aMessage, aTopic) { - if (!aMessage || aTopic != "console-api-log-event") { + if (!_alive || !aMessage || aTopic != "console-api-log-event") { return; } @@ -578,11 +668,7 @@ let ConsoleAPIObserver = { let messages = gConsoleStorage.getEvents(innerWindowId); let result = messages.map(function(aMessage) { - let remoteMessage = { - hudId: Manager.hudId, - id: Manager.sequenceId, - type: "ConsoleAPI", - }; + let remoteMessage = { _type: "ConsoleAPI" }; this._prepareApiMessageForRemote(aMessage.wrappedJSObject, remoteMessage); return remoteMessage; }, this); @@ -609,5 +695,96 @@ let ConsoleAPIObserver = { }, }; +/** + * The nsIConsoleService listener. This is used to send all the page errors + * (JavaScript, CSS and more) to the remote Web Console instance. + */ +let ConsoleListener = { + QueryInterface: XPCOMUtils.generateQI([Ci.nsIConsoleListener]), + + /** + * Initialize the nsIConsoleService listener. + */ + init: function CL_init() + { + Services.console.registerListener(this); + }, + + /** + * The nsIConsoleService observer. This method takes all the script error + * messages belonging to the current window and sends them to the remote Web + * Console instance. + * + * @param nsIScriptError aScriptError + * The script error object coming from the nsIConsoleService. + */ + observe: function CL_observe(aScriptError) + { + if (!_alive || !(aScriptError instanceof Ci.nsIScriptError) || + !aScriptError.outerWindowID) { + return; + } + + switch (aScriptError.category) { + // We ignore chrome-originating errors as we only care about content. + case "XPConnect JavaScript": + case "component javascript": + case "chrome javascript": + case "chrome registration": + case "XBL": + case "XBL Prototype Handler": + case "XBL Content Sink": + case "xbl javascript": + return; + } + + let errorWindow = + WebConsoleUtils.getWindowByOuterId(aScriptError.outerWindowID, + Manager.window); + if (!errorWindow || errorWindow.top != Manager.window) { + return; + } + + Manager.sendMessage("WebConsole:PageError", { pageError: aScriptError }); + }, + + /** + * Get the cached page errors for the current inner window. + * + * @return array + * The array of cached messages. Each element is an nsIScriptError + * with an added _type property so the remote Web Console instance can + * tell the difference between various types of cached messages. + */ + getCachedMessages: function CL_getCachedMessages() + { + let innerWindowId = WebConsoleUtils.getInnerWindowId(Manager.window); + let result = []; + let errors = {}; + Services.console.getMessageArray(errors, {}); + + (errors.value || []).forEach(function(aError) { + if (!(aError instanceof Ci.nsIScriptError) || + aError.innerWindowID != innerWindowId) { + return; + } + + let remoteMessage = WebConsoleUtils.cloneObject(aError); + remoteMessage._type = "PageError"; + result.push(remoteMessage); + }); + + return result; + }, + + /** + * Remove the nsIConsoleService listener. + */ + destroy: function CL_destroy() + { + Services.console.unregisterListener(this); + }, +}; + Manager.init(); -})(this); +})(); diff --git a/browser/devtools/webconsole/HUDService.jsm b/browser/devtools/webconsole/HUDService.jsm index 0ed8991802f..a6b41df9612 100644 --- a/browser/devtools/webconsole/HUDService.jsm +++ b/browser/devtools/webconsole/HUDService.jsm @@ -1503,8 +1503,9 @@ HUD_SERVICE.prototype = let nBox = chromeDocument.defaultView.getNotificationBox(window); let hudId = "hud_" + nBox.id; let displayNode = chromeDocument.getElementById(hudId); + let hudFound = (hudId in this.hudReferences) && displayNode; - if (hudId in this.hudReferences && displayNode) { + if (hudFound) { if (!aAnimated) { this.storeHeight(hudId); } @@ -1533,8 +1534,10 @@ HUD_SERVICE.prototype = } } - let id = WebConsoleUtils.supportsString(hudId); - Services.obs.notifyObservers(id, "web-console-destroyed", null); + if (hudFound) { + let id = WebConsoleUtils.supportsString(hudId); + Services.obs.notifyObservers(id, "web-console-destroyed", null); + } }, /** @@ -1854,8 +1857,6 @@ HUD_SERVICE.prototype = this.startHTTPObservation(); HUDWindowObserver.init(); - HUDConsoleObserver.init(); - ConsoleAPIObserver.init(); }, /** @@ -1880,8 +1881,6 @@ HUD_SERVICE.prototype = delete this.lastFinishedRequestCallback; HUDWindowObserver.uninit(); - HUDConsoleObserver.uninit(); - ConsoleAPIObserver.shutdown(); }, /** @@ -1987,73 +1986,6 @@ HUD_SERVICE.prototype = ConsoleUtils.outputMessageNode(node, aHUDId); }, - /** - * Reports an error in the page source, either JavaScript or CSS. - * - * @param nsIScriptError aScriptError - * The error message to report. - * @return void - */ - reportPageError: function HS_reportPageError(aScriptError) - { - if (!aScriptError.outerWindowID) { - return; - } - - let category; - - switch (aScriptError.category) { - // We ignore chrome-originating errors as we only care about content. - case "XPConnect JavaScript": - case "component javascript": - case "chrome javascript": - case "chrome registration": - case "XBL": - case "XBL Prototype Handler": - case "XBL Content Sink": - case "xbl javascript": - return; - - case "CSS Parser": - case "CSS Loader": - category = CATEGORY_CSS; - break; - - default: - category = CATEGORY_JS; - break; - } - - // Warnings and legacy strict errors become warnings; other types become - // errors. - let severity = SEVERITY_ERROR; - if ((aScriptError.flags & aScriptError.warningFlag) || - (aScriptError.flags & aScriptError.strictFlag)) { - severity = SEVERITY_WARNING; - } - - let window = WebConsoleUtils.getWindowByOuterId(aScriptError.outerWindowID); - if (window) { - let hudId = HUDService.getHudIdByWindow(window.top); - if (hudId) { - let outputNode = this.hudReferences[hudId].outputNode; - let chromeDocument = outputNode.ownerDocument; - - let node = ConsoleUtils.createMessageNode(chromeDocument, - category, - severity, - aScriptError.errorMessage, - hudId, - aScriptError.sourceName, - aScriptError.lineNumber, - null, null, - aScriptError.timeStamp); - - ConsoleUtils.outputMessageNode(node, hudId); - } - } - }, - /** * Register a Gecko app's specialized ApplicationHooks object * @@ -3030,7 +2962,7 @@ HeadsUpDisplay.prototype = { * @type array */ _messageListeners: ["JSTerm:EvalObject", "WebConsole:ConsoleAPI", - "WebConsole:CachedMessages"], + "WebConsole:CachedMessages", "WebConsole:PageError"], consolePanel: null, @@ -3374,42 +3306,30 @@ HeadsUpDisplay.prototype = { * Display cached messages that may have been collected before the UI is * displayed. * + * @private * @param array aRemoteMessages * Array of cached messages coming from the remote Web Console * content instance. */ - displayCachedConsoleMessages: - function HUD_displayCachedConsoleMessages(aRemoteMessages) + _displayCachedConsoleMessages: + function HUD__displayCachedConsoleMessages(aRemoteMessages) { - let innerWindowId = WebConsoleUtils.getInnerWindowId(this.contentWindow); - - let messages = aRemoteMessages; - - let errors = {}; - Services.console.getMessageArray(errors, {}); - - // Filter the errors to find only those we should display. - let filteredErrors = (errors.value || []).filter(function(aError) { - return aError instanceof Ci.nsIScriptError && - aError.innerWindowID == innerWindowId; - }, this); - - messages.push.apply(messages, filteredErrors); - messages.sort(function(a, b) { return a.timeStamp - b.timeStamp; }); + if (!aRemoteMessages.length) { + return; + } // Turn off scrolling for the moment. ConsoleUtils.scroll = false; this.outputNode.hidden = true; - // Display all messages. - messages.forEach(function(aMessage) { - if (aMessage instanceof Ci.nsIScriptError) { - HUDService.reportPageError(aMessage); - } - else { - // In this case the cached message is a console message generated - // by the ConsoleAPI, not an nsIScriptError - this.logConsoleAPIMessage(aMessage); + aRemoteMessages.forEach(function(aMessage) { + switch (aMessage._type) { + case "PageError": + this.reportPageError(aMessage); + break; + case "ConsoleAPI": + this.logConsoleAPIMessage(aMessage); + break; } }, this); @@ -4073,6 +3993,64 @@ HeadsUpDisplay.prototype = { } }, + /** + * Reports an error in the page source, either JavaScript or CSS. + * + * @param nsIScriptError aScriptError + * The error message to report. + */ + reportPageError: function HUD_reportPageError(aScriptError) + { + if (!aScriptError.outerWindowID) { + return; + } + + let category; + + switch (aScriptError.category) { + // We ignore chrome-originating errors as we only care about content. + case "XPConnect JavaScript": + case "component javascript": + case "chrome javascript": + case "chrome registration": + case "XBL": + case "XBL Prototype Handler": + case "XBL Content Sink": + case "xbl javascript": + return; + + case "CSS Parser": + case "CSS Loader": + category = CATEGORY_CSS; + break; + + default: + category = CATEGORY_JS; + break; + } + + // Warnings and legacy strict errors become warnings; other types become + // errors. + let severity = SEVERITY_ERROR; + if ((aScriptError.flags & aScriptError.warningFlag) || + (aScriptError.flags & aScriptError.strictFlag)) { + severity = SEVERITY_WARNING; + } + + let node = ConsoleUtils.createMessageNode(this.chromeDocument, + category, + severity, + aScriptError.errorMessage, + this.hudId, + aScriptError.sourceName, + aScriptError.lineNumber, + null, + null, + aScriptError.timeStamp); + + ConsoleUtils.outputMessageNode(node, this.hudId); + }, + ERRORS: { HUD_BOX_DOES_NOT_EXIST: "Heads Up Display does not exist", TAB_ID_REQUIRED: "Tab DOM ID is required", @@ -4096,8 +4074,8 @@ HeadsUpDisplay.prototype = { let message = { hudId: this.hudId, - features: ["ConsoleAPI", "JSTerm"], - cachedMessages: ["ConsoleAPI"], + features: ["ConsoleAPI", "JSTerm", "PageError"], + cachedMessages: ["ConsoleAPI", "PageError"], }; this.sendMessageToContent("WebConsole:Init", message); }, @@ -4124,8 +4102,11 @@ HeadsUpDisplay.prototype = { case "WebConsole:ConsoleAPI": this.logConsoleAPIMessage(aMessage.json); break; + case "WebConsole:PageError": + this.reportPageError(aMessage.json.pageError); + break; case "WebConsole:CachedMessages": - this.displayCachedConsoleMessages(aMessage.json.messages); + this._displayCachedConsoleMessages(aMessage.json.messages); this._onInitComplete(); break; } @@ -4277,33 +4258,6 @@ HeadsUpDisplay.prototype = { }, }; - -////////////////////////////////////////////////////////////////////////////// -// ConsoleAPIObserver -////////////////////////////////////////////////////////////////////////////// - -let ConsoleAPIObserver = { - - QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver]), - - init: function CAO_init() - { - Services.obs.addObserver(this, "quit-application-granted", false); - }, - - observe: function CAO_observe(aMessage, aTopic, aData) - { - if (aTopic == "quit-application-granted") { - HUDService.shutdown(); - } - }, - - shutdown: function CAO_shutdown() - { - Services.obs.removeObserver(this, "quit-application-granted"); - } -}; - /** * Creates a DOM Node factory for XUL nodes - as well as textNodes * @param aFactoryType "xul" or "text" @@ -4853,6 +4807,7 @@ function JSTerm(aContext, aParentNode, aMixin, aConsole) } this.hudId = node.getAttribute("id"); + this.history = []; this.historyIndex = 0; this.historyPlaceHolder = 0; // this.history.length; this.log = LogFactory("*** JSTerm:"); @@ -5474,7 +5429,7 @@ JSTerm.prototype = { node.selectionStart == 0 && !multiline; }, - history: [], + history: null, // Stores the data for the last completion. lastCompletion: null, @@ -6485,14 +6440,12 @@ ConsoleEntry.prototype = { ////////////////////////////////////////////////////////////////////////// HUDWindowObserver = { - QueryInterface: XPCOMUtils.generateQI( - [Ci.nsIObserver,] - ), + QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver]), init: function HWO_init() { - Services.obs.addObserver(this, "xpcom-shutdown", false); Services.obs.addObserver(this, "content-document-global-created", false); + Services.obs.addObserver(this, "quit-application-granted", false); }, observe: function HWO_observe(aSubject, aTopic, aData) @@ -6500,16 +6453,15 @@ HUDWindowObserver = { if (aTopic == "content-document-global-created") { HUDService.windowInitializer(aSubject); } - else if (aTopic == "xpcom-shutdown") { - this.uninit(); + else if (aTopic == "quit-application-granted") { + HUDService.shutdown(); } }, uninit: function HWO_uninit() { Services.obs.removeObserver(this, "content-document-global-created"); - Services.obs.removeObserver(this, "xpcom-shutdown"); - this.initialConsoleCreated = false; + Services.obs.removeObserver(this, "quit-application-granted"); }, }; @@ -6604,44 +6556,6 @@ CommandController.prototype = { } }; -/////////////////////////////////////////////////////////////////////////////// -// HUDConsoleObserver -/////////////////////////////////////////////////////////////////////////////// - -/** - * HUDConsoleObserver: Observes nsIConsoleService for global consoleMessages, - * if a message originates inside a contentWindow we are tracking, - * then route that message to the HUDService for logging. - */ - -HUDConsoleObserver = { - QueryInterface: XPCOMUtils.generateQI( - [Ci.nsIObserver] - ), - - init: function HCO_init() - { - Services.console.registerListener(this); - Services.obs.addObserver(this, "quit-application-granted", false); - }, - - uninit: function HCO_uninit() - { - Services.console.unregisterListener(this); - Services.obs.removeObserver(this, "quit-application-granted"); - }, - - observe: function HCO_observe(aSubject, aTopic, aData) - { - if (aTopic == "quit-application-granted") { - this.uninit(); - } - else if (aSubject instanceof Ci.nsIScriptError) { - HUDService.reportPageError(aSubject); - } - } -}; - /** * A WebProgressListener that listens for location changes, to update HUDService * state information on page navigation. diff --git a/browser/devtools/webconsole/test/browser_cached_messages.js b/browser/devtools/webconsole/test/browser_cached_messages.js index b3efcd51066..9f291f741b4 100644 --- a/browser/devtools/webconsole/test/browser_cached_messages.js +++ b/browser/devtools/webconsole/test/browser_cached_messages.js @@ -56,7 +56,7 @@ function testOpenUI(aTestReopen) // test to see if the messages are // displayed when the console UI is opened - openConsole(function(hud) { + openConsole(null, function(hud) { testLogEntry(hud.outputNode, "log Bazzle", "Find a console log entry from before console UI is opened", false, null); diff --git a/browser/devtools/webconsole/test/browser_webconsole_bug_580030_errors_after_page_reload.js b/browser/devtools/webconsole/test/browser_webconsole_bug_580030_errors_after_page_reload.js index 394cc90e711..68eae40a419 100644 --- a/browser/devtools/webconsole/test/browser_webconsole_bug_580030_errors_after_page_reload.js +++ b/browser/devtools/webconsole/test/browser_webconsole_bug_580030_errors_after_page_reload.js @@ -51,33 +51,26 @@ function test() { // see bug 580030: the error handler fails silently after page reload. // https://bugzilla.mozilla.org/show_bug.cgi?id=580030 function onLoad(aEvent) { - browser.removeEventListener(aEvent.type, arguments.callee, true); + browser.removeEventListener(aEvent.type, onLoad, true); - openConsole(); - - browser.addEventListener("load", testErrorsAfterPageReload, true); - executeSoon(function() { + openConsole(null, function(hud) { + hud.jsterm.clearOutput(); + browser.addEventListener("load", testErrorsAfterPageReload, true); content.location.reload(); }); } function testErrorsAfterPageReload(aEvent) { - browser.removeEventListener(aEvent.type, arguments.callee, true); + browser.removeEventListener(aEvent.type, testErrorsAfterPageReload, true); // dispatch a click event to the button in the test page and listen for // errors. Services.console.registerListener(consoleObserver); - var button = content.document.querySelector("button").wrappedJSObject; - var clickEvent = content.document.createEvent("MouseEvents"); - clickEvent.initMouseEvent("click", true, true, - content, 0, 0, 0, 0, 0, false, false, - false, false, 0, null); - - executeSoon(function() { - button.dispatchEvent(clickEvent); - }); + let button = content.document.querySelector("button").wrappedJSObject; + ok(button, "button found"); + EventUtils.sendMouseEvent({type: "click"}, button, content); } var consoleObserver = { @@ -95,10 +88,14 @@ var consoleObserver = { let outputNode = HUDService.getHudByWindow(content).outputNode; - executeSoon(function() { - let msg = "Found the error message after page reload"; - testLogEntry(outputNode, "fooBazBaz", msg); - finishTest(); + waitForSuccess({ + name: "error message after page reload", + validatorFn: function() + { + return outputNode.textContent.indexOf("fooBazBaz") > -1; + }, + successFn: finishTest, + failureFn: finishTest, }); } }; diff --git a/browser/devtools/webconsole/test/browser_webconsole_bug_582201_duplicate_errors.js b/browser/devtools/webconsole/test/browser_webconsole_bug_582201_duplicate_errors.js index ec0921dc1c3..2864823795b 100644 --- a/browser/devtools/webconsole/test/browser_webconsole_bug_582201_duplicate_errors.js +++ b/browser/devtools/webconsole/test/browser_webconsole_bug_582201_duplicate_errors.js @@ -52,7 +52,7 @@ function test() { function testDuplicateErrors() { browser.removeEventListener("DOMContentLoaded", testDuplicateErrors, false); - openConsole(function(hud) { + openConsole(null, function(hud) { hud.jsterm.clearOutput(); Services.console.registerListener(consoleObserver); @@ -77,18 +77,27 @@ var consoleObserver = { outputNode = HUDService.getHudByWindow(content).outputNode; - executeSoon(function () { - var text = outputNode.textContent; - var error1pos = text.indexOf("fooDuplicateError1"); - ok(error1pos > -1, "found fooDuplicateError1"); - if (error1pos > -1) { - ok(text.indexOf("fooDuplicateError1", error1pos + 1) == -1, - "no duplicate for fooDuplicateError1"); - } + waitForSuccess({ + name: "fooDuplicateError1 error displayed", + validatorFn: function() + { + return outputNode.textContent.indexOf("fooDuplicateError1") > -1; + }, + successFn: function() + { + let text = outputNode.textContent; + let error1pos = text.indexOf("fooDuplicateError1"); + ok(error1pos > -1, "found fooDuplicateError1"); + if (error1pos > -1) { + ok(text.indexOf("fooDuplicateError1", error1pos + 1) == -1, + "no duplicate for fooDuplicateError1"); + } - findLogEntry("test-duplicate-error.html"); + findLogEntry("test-duplicate-error.html"); - finishTest(); + finishTest(); + }, + failureFn: finishTest, }); } }; diff --git a/browser/devtools/webconsole/test/browser_webconsole_bug_585237_line_limit.js b/browser/devtools/webconsole/test/browser_webconsole_bug_585237_line_limit.js index 2a24055277d..b2ff1432b31 100644 --- a/browser/devtools/webconsole/test/browser_webconsole_bug_585237_line_limit.js +++ b/browser/devtools/webconsole/test/browser_webconsole_bug_585237_line_limit.js @@ -19,7 +19,7 @@ function test() { addTab(TEST_URI); browser.addEventListener("load", function onLoad() { browser.removeEventListener("load", onLoad, true); - openConsole(function(aHud) { + openConsole(null, function(aHud) { hud = aHud; testDriver = testGen(); testNext(); diff --git a/browser/devtools/webconsole/test/browser_webconsole_bug_585956_console_trace.js b/browser/devtools/webconsole/test/browser_webconsole_bug_585956_console_trace.js index d8665a41d94..3bfc9deba6a 100644 --- a/browser/devtools/webconsole/test/browser_webconsole_bug_585956_console_trace.js +++ b/browser/devtools/webconsole/test/browser_webconsole_bug_585956_console_trace.js @@ -46,7 +46,7 @@ function test() { function tabLoaded() { browser.removeEventListener("load", tabLoaded, true); - openConsole(function() { + openConsole(null, function() { browser.addEventListener("load", tabReloaded, true); content.location.reload(); }); diff --git a/browser/devtools/webconsole/test/browser_webconsole_bug_587617_output_copy.js b/browser/devtools/webconsole/test/browser_webconsole_bug_587617_output_copy.js index 87e433587c6..7db34195eae 100644 --- a/browser/devtools/webconsole/test/browser_webconsole_bug_587617_output_copy.js +++ b/browser/devtools/webconsole/test/browser_webconsole_bug_587617_output_copy.js @@ -14,7 +14,7 @@ function test() { addTab(TEST_URI); browser.addEventListener("load", function onLoad() { browser.removeEventListener("load", onLoad, true); - openConsole(consoleOpened); + openConsole(null, consoleOpened); }, true); } diff --git a/browser/devtools/webconsole/test/browser_webconsole_bug_588730_text_node_insertion.js b/browser/devtools/webconsole/test/browser_webconsole_bug_588730_text_node_insertion.js index 06442f663dc..bbd48456c75 100644 --- a/browser/devtools/webconsole/test/browser_webconsole_bug_588730_text_node_insertion.js +++ b/browser/devtools/webconsole/test/browser_webconsole_bug_588730_text_node_insertion.js @@ -46,7 +46,7 @@ function test() { addTab(TEST_URI); browser.addEventListener("load", function onLoad() { browser.removeEventListener("load", onLoad, true); - openConsole(testTextNodeInsertion); + openConsole(null, testTextNodeInsertion); }, true); } diff --git a/browser/devtools/webconsole/test/browser_webconsole_bug_593003_iframe_wrong_hud.js b/browser/devtools/webconsole/test/browser_webconsole_bug_593003_iframe_wrong_hud.js index 488fc6ea354..ab66cf6d69d 100644 --- a/browser/devtools/webconsole/test/browser_webconsole_bug_593003_iframe_wrong_hud.js +++ b/browser/devtools/webconsole/test/browser_webconsole_bug_593003_iframe_wrong_hud.js @@ -50,45 +50,27 @@ function test() { browser.addEventListener("load", tab1Loaded, true); } -/** - * Check if a log entry exists in the HUD output node. - * - * @param {Element} aOutputNode the HUD output node. - * @param {string} aMatchString the string you want to check if it exists in the - * output node. - * @param {boolean} [aOnlyVisible=false] find only messages that are visible, - * not hidden by the filter. - * @param {boolean} [aFailIfFound=false] fail the test if the string is found in - * the output node. - */ - function tab1Loaded(aEvent) { - browser.removeEventListener(aEvent.type, arguments.callee, true); - browser.contentWindow.wrappedJSObject.console.log("FOO"); - try { - openConsole(); - } - catch (ex) { - log(ex); - log(ex.stack); - } - - tab2 = gBrowser.addTab(TEST_DUMMY_URI); - gBrowser.selectedTab = tab2; - gBrowser.selectedBrowser.addEventListener("load", tab2Loaded, true); + browser.removeEventListener(aEvent.type, tab1Loaded, true); + content.console.log("FOO"); + openConsole(null, function() { + tab2 = gBrowser.addTab(TEST_DUMMY_URI); + gBrowser.selectedTab = tab2; + gBrowser.selectedBrowser.addEventListener("load", tab2Loaded, true); + }); } function tab2Loaded(aEvent) { - tab2.linkedBrowser.removeEventListener(aEvent.type, arguments.callee, true); + tab2.linkedBrowser.removeEventListener(aEvent.type, tab2Loaded, true); - HUDService.activateHUDForContext(gBrowser.selectedTab); - - tab1.linkedBrowser.addEventListener("load", tab1Reloaded, true); - tab1.linkedBrowser.contentWindow.location.reload(); + openConsole(gBrowser.selectedTab, function() { + tab1.linkedBrowser.addEventListener("load", tab1Reloaded, true); + tab1.linkedBrowser.contentWindow.location.reload(); + }); } function tab1Reloaded(aEvent) { - tab1.linkedBrowser.removeEventListener(aEvent.type, arguments.callee, true); + tab1.linkedBrowser.removeEventListener(aEvent.type, tab1Reloaded, true); let hud1 = HUDService.getHudByWindow(tab1.linkedBrowser.contentWindow); let outputNode1 = hud1.outputNode; @@ -105,8 +87,9 @@ function tab1Reloaded(aEvent) { msg = "Didn't find the iframe network request in tab2"; testLogEntry(outputNode2, TEST_IFRAME_URI, msg, true, true); - HUDService.deactivateHUDForContext(tab2); - gBrowser.removeTab(tab2); - - finishTest(); + closeConsole(tab2, function() { + gBrowser.removeTab(tab2); + tab1 = tab2 = null; + executeSoon(finishTest); + }); } diff --git a/browser/devtools/webconsole/test/browser_webconsole_bug_595350_multiple_windows_and_tabs.js b/browser/devtools/webconsole/test/browser_webconsole_bug_595350_multiple_windows_and_tabs.js index d6367debde2..fd807a93838 100644 --- a/browser/devtools/webconsole/test/browser_webconsole_bug_595350_multiple_windows_and_tabs.js +++ b/browser/devtools/webconsole/test/browser_webconsole_bug_595350_multiple_windows_and_tabs.js @@ -28,7 +28,7 @@ function test() { } function onWindowLoad(aEvent) { - win2.removeEventListener(aEvent.type, arguments.callee, true); + win2.removeEventListener(aEvent.type, onWindowLoad, true); // Add two tabs in the new window. addTabs(win2); @@ -39,48 +39,71 @@ function addTabs(aWindow) { let tab = aWindow.gBrowser.addTab(TEST_URI); openTabs.push(tab); - tab.linkedBrowser.addEventListener("load", function(aEvent) { - tab.linkedBrowser.removeEventListener(aEvent.type, arguments.callee, - true); + tab.linkedBrowser.addEventListener("load", function onLoad(aEvent) { + tab.linkedBrowser.removeEventListener(aEvent.type, onLoad, true); loadedTabCount++; if (loadedTabCount >= 4) { - executeSoon(performTest); + executeSoon(openConsoles); } }, true); } } -function performTest() { +function openConsoles() { // open the Web Console for each of the four tabs and log a message. + let consolesOpen = 0; for (let i = 0; i < openTabs.length; i++) { let tab = openTabs[i]; - HUDService.activateHUDForContext(tab); - let hudId = HUDService.getHudIdByWindow(tab.linkedBrowser.contentWindow); - ok(hudId, "HUD is open for tab " + i); - let HUD = HUDService.hudReferences[hudId]; - HUD.console.log("message for tab " + i); + openConsole(tab, function(index, hud) { + ok(hud, "HUD is open for tab " + index); + hud.console.log("message for tab " + index); + consolesOpen++; + }.bind(null, i)); } - let displays = Object.keys(HUDService.hudReferences); - is(displays.length, 4, "four displays found"); - - win2.close(); - - executeSoon(function() { - win1.gBrowser.removeTab(openTabs[0]); - win1.gBrowser.removeTab(openTabs[1]); - - executeSoon(function() { - displays = Object.keys(HUDService.hudReferences); - is(displays.length, 0, "no displays found"); - ok(!HUDService.storage, "no storage found"); - ok(!HUDService.httpObserver, "no httpObserver found"); - - displays = openTabs = win1 = win2 = null; - - finishTest(); - }); + waitForSuccess({ + name: "4 web consoles opened", + validatorFn: function() + { + return consolesOpen == 4; + }, + successFn: closeConsoles, + failureFn: closeConsoles, + }); +} + +function closeConsoles() { + let consolesClosed = 0; + + function onWebConsoleClose(aSubject, aTopic) { + if (aTopic == "web-console-destroyed") { + consolesClosed++; + } + } + + Services.obs.addObserver(onWebConsoleClose, "web-console-destroyed", false); + + win2.close(); + + win1.gBrowser.removeTab(openTabs[0]); + win1.gBrowser.removeTab(openTabs[1]); + + openTabs = win1 = win2 = null; + + function onTimeout() { + Services.obs.removeObserver(onWebConsoleClose, "web-console-destroyed"); + executeSoon(finishTest); + } + + waitForSuccess({ + name: "4 web consoles closed", + validatorFn: function() + { + return consolesClosed == 4; + }, + successFn: onTimeout, + failureFn: onTimeout, }); } diff --git a/browser/devtools/webconsole/test/browser_webconsole_bug_595934_message_categories.js b/browser/devtools/webconsole/test/browser_webconsole_bug_595934_message_categories.js index 2c24a70e73c..aaeadd1f196 100644 --- a/browser/devtools/webconsole/test/browser_webconsole_bug_595934_message_categories.js +++ b/browser/devtools/webconsole/test/browser_webconsole_bug_595934_message_categories.js @@ -89,12 +89,12 @@ const TESTS = [ category: "Image", matchString: "corrupt", }, - /* Disabled until bug 675221 lands. - { // #7 + { // #15 file: "test-bug-595934-workers.html", category: "Web Worker", matchString: "fooBarWorker", - },*/ + expectError: true, + }, ]; let pos = -1; @@ -103,13 +103,14 @@ let foundCategory = false; let foundText = false; let output = null; let jsterm = null; +let testEnded = false; let TestObserver = { QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver]), observe: function test_observe(aSubject) { - if (!(aSubject instanceof Ci.nsIScriptError)) { + if (testEnded || !(aSubject instanceof Ci.nsIScriptError)) { return; } @@ -125,24 +126,21 @@ let TestObserver = { else { ok(false, aSubject.sourceName + ':' + aSubject.lineNumber + '; ' + aSubject.errorMessage); - executeSoon(finish); + testEnded = true; + executeSoon(finishTest); } } }; -function tabLoad(aEvent) { - browser.removeEventListener(aEvent.type, arguments.callee, true); - - openConsole(); - - let hudId = HUDService.getHudIdByWindow(content); - let hud = HUDService.hudReferences[hudId]; +function consoleOpened(hud) { output = hud.outputNode; output.addEventListener("DOMNodeInserted", onDOMNodeInserted, false); jsterm = hud.jsterm; Services.console.registerListener(TestObserver); + registerCleanupFunction(testEnd); + executeSoon(testNext); } @@ -156,26 +154,30 @@ function testNext() { let test = TESTS[pos]; let testLocation = TESTS_PATH + test.file; if (test.onload) { - browser.addEventListener("load", function(aEvent) { + browser.addEventListener("load", function onLoad(aEvent) { if (content.location.href == testLocation) { - browser.removeEventListener(aEvent.type, arguments.callee, true); + browser.removeEventListener(aEvent.type, onLoad, true); test.onload(aEvent); } }, true); } + if (test.expectError) { + expectUncaughtException(); + } + content.location = testLocation; } else { - executeSoon(finish); + testEnded = true; + executeSoon(finishTest); } } function testEnd() { Services.console.unregisterListener(TestObserver); output.removeEventListener("DOMNodeInserted", onDOMNodeInserted, false); - output = jsterm = null; - finishTest(); + TestObserver = output = jsterm = null; } function onDOMNodeInserted(aEvent) { @@ -191,9 +193,10 @@ function onDOMNodeInserted(aEvent) { } function test() { - registerCleanupFunction(testEnd); - addTab("data:text/html;charset=utf-8,Web Console test for bug 595934 - message categories coverage."); - browser.addEventListener("load", tabLoad, true); + browser.addEventListener("load", function onLoad() { + browser.removeEventListener("load", onLoad, true); + openConsole(null, consoleOpened); + }, true); } diff --git a/browser/devtools/webconsole/test/browser_webconsole_bug_597136_external_script_errors.js b/browser/devtools/webconsole/test/browser_webconsole_bug_597136_external_script_errors.js index 8ddf8ea49d5..0e96b26325f 100644 --- a/browser/devtools/webconsole/test/browser_webconsole_bug_597136_external_script_errors.js +++ b/browser/devtools/webconsole/test/browser_webconsole_bug_597136_external_script_errors.js @@ -21,25 +21,19 @@ function tabLoaded(aEvent) { browser.removeEventListener("load", tabLoaded, true); openConsole(); - browser.addEventListener("load", contentLoaded, true); - content.location.reload(); -} - -function contentLoaded(aEvent) { - browser.removeEventListener("load", contentLoaded, true); - let button = content.document.querySelector("button"); - expectUncaughtException(); - EventUtils.sendMouseEvent({ type: "click" }, button, content); - executeSoon(buttonClicked); -} - -function buttonClicked() { let outputNode = HUDService.getHudByWindow(content).outputNode; - let msg = "the error from the external script was logged"; - testLogEntry(outputNode, "bogus", msg); + expectUncaughtException(); + EventUtils.sendMouseEvent({ type: "click" }, button, content); - finishTest(); + waitForSuccess({ + name: "external script error message", + validatorFn: function() + { + return outputNode.textContent.indexOf("bogus is not defined") > -1; + }, + successFn: finishTest, + failureFn: finishTest, + }); } - diff --git a/browser/devtools/webconsole/test/browser_webconsole_bug_597756_reopen_closed_tab.js b/browser/devtools/webconsole/test/browser_webconsole_bug_597756_reopen_closed_tab.js index df2279e0f09..a27b6eb3986 100644 --- a/browser/devtools/webconsole/test/browser_webconsole_bug_597756_reopen_closed_tab.js +++ b/browser/devtools/webconsole/test/browser_webconsole_bug_597756_reopen_closed_tab.js @@ -13,17 +13,17 @@ const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/te let newTabIsOpen = false; function tabLoaded(aEvent) { - gBrowser.selectedBrowser.removeEventListener(aEvent.type, arguments.callee, true); + gBrowser.selectedBrowser.removeEventListener(aEvent.type, tabLoaded, true); - HUDService.activateHUDForContext(gBrowser.selectedTab); - - gBrowser.selectedBrowser.addEventListener("load", tabReloaded, true); - expectUncaughtException(); - content.location.reload(); + openConsole(gBrowser.selectedTab, function() { + gBrowser.selectedBrowser.addEventListener("load", tabReloaded, true); + expectUncaughtException(); + content.location.reload(); + }); } function tabReloaded(aEvent) { - gBrowser.selectedBrowser.removeEventListener(aEvent.type, arguments.callee, true); + gBrowser.selectedBrowser.removeEventListener(aEvent.type, tabReloaded, true); let hudId = HUDService.getHudIdByWindow(content); let HUD = HUDService.hudReferences[hudId]; @@ -34,26 +34,24 @@ function tabReloaded(aEvent) { executeSoon(function() { if (newTabIsOpen) { - testEnd(); + executeSoon(finishTest); return; } - let newTab = gBrowser.addTab(); - gBrowser.removeCurrentTab(); - gBrowser.selectedTab = newTab; + closeConsole(gBrowser.selectedTab, function() { + gBrowser.removeCurrentTab(); - newTabIsOpen = true; - gBrowser.selectedBrowser.addEventListener("load", tabLoaded, true); - expectUncaughtException(); - content.location = TEST_URI; + let newTab = gBrowser.addTab(); + gBrowser.selectedTab = newTab; + + newTabIsOpen = true; + gBrowser.selectedBrowser.addEventListener("load", tabLoaded, true); + expectUncaughtException(); + content.location = TEST_URI; + }); }); } -function testEnd() { - gBrowser.removeCurrentTab(); - executeSoon(finishTest); -} - function test() { expectUncaughtException(); addTab(TEST_URI); diff --git a/browser/devtools/webconsole/test/browser_webconsole_bug_598357_jsterm_output.js b/browser/devtools/webconsole/test/browser_webconsole_bug_598357_jsterm_output.js index f921d1b2c1f..c3e8920d2e6 100644 --- a/browser/devtools/webconsole/test/browser_webconsole_bug_598357_jsterm_output.js +++ b/browser/devtools/webconsole/test/browser_webconsole_bug_598357_jsterm_output.js @@ -98,7 +98,7 @@ function tabLoad(aEvent) { browser.removeEventListener(aEvent.type, tabLoad, true); waitForFocus(function () { - openConsole(function(aHud) { + openConsole(null, function(aHud) { HUD = aHud; testNext(); }); diff --git a/browser/devtools/webconsole/test/browser_webconsole_bug_601352_scroll.js b/browser/devtools/webconsole/test/browser_webconsole_bug_601352_scroll.js index c7e914477e5..c080b19f0f0 100644 --- a/browser/devtools/webconsole/test/browser_webconsole_bug_601352_scroll.js +++ b/browser/devtools/webconsole/test/browser_webconsole_bug_601352_scroll.js @@ -66,7 +66,7 @@ function test() { addTab("data:text/html;charset=utf-8,Web Console test for bug 601352"); browser.addEventListener("load", function tabLoad(aEvent) { browser.removeEventListener(aEvent.type, tabLoad, true); - openConsole(consoleOpened); + openConsole(null, consoleOpened); }, true); } diff --git a/browser/devtools/webconsole/test/browser_webconsole_bug_602572_log_bodies_checkbox.js b/browser/devtools/webconsole/test/browser_webconsole_bug_602572_log_bodies_checkbox.js index 200b5653274..2cec9e1b108 100644 --- a/browser/devtools/webconsole/test/browser_webconsole_bug_602572_log_bodies_checkbox.js +++ b/browser/devtools/webconsole/test/browser_webconsole_bug_602572_log_bodies_checkbox.js @@ -16,21 +16,20 @@ function test() addTab("data:text/html;charset=utf-8,Web Console test for bug 602572: log bodies checkbox. tab 1"); tabs.push(tab); - browser.addEventListener("load", function(aEvent) { - browser.removeEventListener(aEvent.type, arguments.callee, true); + browser.addEventListener("load", function onLoad1(aEvent) { + browser.removeEventListener(aEvent.type, onLoad1, true); - openConsole(); + openConsole(null, function() { + // open tab 2 + addTab("data:text/html;charset=utf-8,Web Console test for bug 602572: log bodies checkbox. tab 2"); + tabs.push(tab); - // open tab 2 - addTab("data:text/html;charset=utf-8,Web Console test for bug 602572: log bodies checkbox. tab 2"); - tabs.push(tab); + browser.addEventListener("load", function onLoad2(aEvent) { + browser.removeEventListener(aEvent.type, onLoad2, true); - browser.addEventListener("load", function(aEvent) { - browser.removeEventListener(aEvent.type, arguments.callee, true); - - openConsole(); - executeSoon(startTest); - }, true); + openConsole(null, startTest); + }, true); + }); }, true); } @@ -52,7 +51,7 @@ function startTest() function onpopupshown2(aEvent) { - menupopups[1].removeEventListener(aEvent.type, arguments.callee, false); + menupopups[1].removeEventListener(aEvent.type, onpopupshown2, false); // By default bodies are not logged. isnot(menuitems[1].getAttribute("checked"), "true", @@ -63,8 +62,8 @@ function onpopupshown2(aEvent) // Enable body logging. HUDService.saveRequestAndResponseBodies = true; - menupopups[1].addEventListener("popuphidden", function(aEvent) { - menupopups[1].removeEventListener(aEvent.type, arguments.callee, false); + menupopups[1].addEventListener("popuphidden", function _onhidden(aEvent) { + menupopups[1].removeEventListener(aEvent.type, _onhidden, false); // Reopen the context menu. menupopups[1].addEventListener("popupshown", onpopupshown2b, false); @@ -75,11 +74,11 @@ function onpopupshown2(aEvent) function onpopupshown2b(aEvent) { - menupopups[1].removeEventListener(aEvent.type, arguments.callee, false); + menupopups[1].removeEventListener(aEvent.type, onpopupshown2b, false); is(menuitems[1].getAttribute("checked"), "true", "menuitems[1] is checked"); - menupopups[1].addEventListener("popuphidden", function(aEvent) { - menupopups[1].removeEventListener(aEvent.type, arguments.callee, false); + menupopups[1].addEventListener("popuphidden", function _onhidden(aEvent) { + menupopups[1].removeEventListener(aEvent.type, _onhidden, false); // Switch to tab 1 and open the Web Console context menu from there. gBrowser.selectedTab = tabs[0]; @@ -102,7 +101,7 @@ function onpopupshown2b(aEvent) function onpopupshown1(aEvent) { - menupopups[0].removeEventListener(aEvent.type, arguments.callee, false); + menupopups[0].removeEventListener(aEvent.type, onpopupshown1, false); // The menuitem checkbox must be in sync with the other tabs. is(menuitems[0].getAttribute("checked"), "true", "menuitems[0] is checked"); @@ -111,8 +110,8 @@ function onpopupshown1(aEvent) HUDService.saveRequestAndResponseBodies = false; // Close the menu, and switch back to tab 2. - menupopups[0].addEventListener("popuphidden", function(aEvent) { - menupopups[0].removeEventListener(aEvent.type, arguments.callee, false); + menupopups[0].addEventListener("popuphidden", function _onhidden(aEvent) { + menupopups[0].removeEventListener(aEvent.type, _onhidden, false); gBrowser.selectedTab = tabs[1]; waitForFocus(function() { @@ -126,19 +125,20 @@ function onpopupshown1(aEvent) function onpopupshown2c(aEvent) { - menupopups[1].removeEventListener(aEvent.type, arguments.callee, false); + menupopups[1].removeEventListener(aEvent.type, onpopupshown2c, false); isnot(menuitems[1].getAttribute("checked"), "true", "menuitems[1] is not checked"); - menupopups[1].addEventListener("popuphidden", function(aEvent) { - menupopups[1].removeEventListener(aEvent.type, arguments.callee, false); + menupopups[1].addEventListener("popuphidden", function _onhidden(aEvent) { + menupopups[1].removeEventListener(aEvent.type, _onhidden, false); // Done! huds = menuitems = menupopups = tabs = null; - HUDService.deactivateHUDForContext(gBrowser.selectedTab); - gBrowser.removeCurrentTab(); - executeSoon(finishTest); + closeConsole(gBrowser.selectedTab, function() { + gBrowser.removeCurrentTab(); + executeSoon(finishTest); + }); }, false); menupopups[1].hidePopup(); } diff --git a/browser/devtools/webconsole/test/browser_webconsole_bug_603750_websocket.js b/browser/devtools/webconsole/test/browser_webconsole_bug_603750_websocket.js index 62adbe72be7..ae0c180cbf3 100644 --- a/browser/devtools/webconsole/test/browser_webconsole_bug_603750_websocket.js +++ b/browser/devtools/webconsole/test/browser_webconsole_bug_603750_websocket.js @@ -39,7 +39,7 @@ let TestObserver = { }; function tabLoad(aEvent) { - browser.removeEventListener(aEvent.type, arguments.callee, true); + browser.removeEventListener(aEvent.type, tabLoad, true); openConsole(); @@ -52,15 +52,20 @@ function tabLoad(aEvent) { } function performTest() { - let textContent = hud.outputNode.textContent; - isnot(textContent.indexOf("ws://0.0.0.0:81"), -1, - "first error message found"); - isnot(textContent.indexOf("ws://0.0.0.0:82"), -1, - "second error message found"); - Services.console.unregisterListener(TestObserver); Services.prefs.setBoolPref(pref_ws, oldPref_ws); - finishTest(); + + waitForSuccess({ + name: "websocket error messages displayed", + validatorFn: function() + { + let textContent = hud.outputNode.textContent; + return textContent.indexOf("ws://0.0.0.0:81") > -1 && + textContent.indexOf("ws://0.0.0.0:82") > -1; + }, + successFn: finishTest, + failureFn: finishTest, + }); } function test() { diff --git a/browser/devtools/webconsole/test/browser_webconsole_bug_611795.js b/browser/devtools/webconsole/test/browser_webconsole_bug_611795.js index f70092b027f..a62bd4c352c 100644 --- a/browser/devtools/webconsole/test/browser_webconsole_bug_611795.js +++ b/browser/devtools/webconsole/test/browser_webconsole_bug_611795.js @@ -7,17 +7,39 @@ const TEST_URI = 'data:text/html;charset=utf-8,