From b409cdbd9596e9edd8a0486bc6dfadfb97e75336 Mon Sep 17 00:00:00 2001 From: Mihai Sucan Date: Thu, 23 Dec 2010 13:07:03 -0400 Subject: [PATCH] Bug 611789 - Web Console cleanup: Remove the window registry; f=rcampbell r=sdwilsh a=blocking2.0 --- .../console/hudservice/HUDService.jsm | 352 ++++-------------- ...wser_webconsole_bug_581231_close_button.js | 2 +- .../browser_webconsole_display_accessors.js | 2 - .../browser/browser_webconsole_registries.js | 8 +- 4 files changed, 84 insertions(+), 280 deletions(-) diff --git a/toolkit/components/console/hudservice/HUDService.jsm b/toolkit/components/console/hudservice/HUDService.jsm index 08ab2170334..6f02c0b6ff9 100644 --- a/toolkit/components/console/hudservice/HUDService.jsm +++ b/toolkit/components/console/hudservice/HUDService.jsm @@ -1170,24 +1170,9 @@ HUD_SERVICE.prototype = activatedContexts: [], /** - * Registry of HeadsUpDisplay DOM node ids + * Collection of outer window IDs mapping to HUD IDs. */ - _headsUpDisplays: {}, - - /** - * Mapping of HUDIds to URIspecs - */ - displayRegistry: {}, - - /** - * Mapping of HUDIds to contentWindows. - */ - windowRegistry: {}, - - /** - * Mapping of URISpecs to HUDIds - */ - uriRegistry: {}, + windowIds: {}, /** * The sequencer is a generator (after initialization) that returns unique @@ -1220,9 +1205,21 @@ HUD_SERVICE.prototype = */ getWindowByWindowId: function HS_getWindowByWindowId(aId) { + // In the future (post-Electrolysis), getOuterWindowWithId() could + // return null, because the originating window could have gone away + // while we were in the process of receiving and/or processing a + // message. For future-proofing purposes, we do a null check here. + let someWindow = Services.wm.getMostRecentWindow(null); - let windowUtils = someWindow.getInterface(Ci.nsIDOMWindowUtils); - return windowUtils.getOuterWindowWithId(aId); + let content = null; + + if (someWindow) { + let windowUtils = someWindow.QueryInterface(Ci.nsIInterfaceRequestor) + .getInterface(Ci.nsIDOMWindowUtils); + content = windowUtils.getOuterWindowWithId(aId); + } + + return content; }, /** @@ -1295,13 +1292,14 @@ HUD_SERVICE.prototype = { this.wakeup(); - var window = aContext.linkedBrowser.contentWindow; - var id = aContext.linkedBrowser.parentNode.parentNode.getAttribute("id"); - this.registerActiveContext(id); + let window = aContext.linkedBrowser.contentWindow; + let nBox = aContext.ownerDocument.defaultView. + getNotificationBox(window); + this.registerActiveContext(nBox.id); this.windowInitializer(window); if (!aAnimated) { - this.disableAnimation("hud_" + id); + this.disableAnimation("hud_" + nBox.id); } }, @@ -1320,12 +1318,11 @@ HUD_SERVICE.prototype = let hudId = "hud_" + nBox.id; let displayNode = nBox.querySelector("#" + hudId); - if (hudId in this.displayRegistry && displayNode) { + if (hudId in this.hudReferences && displayNode) { if (!aAnimated) { this.storeHeight(hudId); } - this.unregisterActiveContext(hudId); this.unregisterDisplay(displayNode); window.focus(); } @@ -1582,66 +1579,20 @@ HUD_SERVICE.prototype = this.hudReferences[aHUD.hudId] = aHUD; }, - /** - * Deletes a HeadsUpDisplay object from memory - * - * @param string aHUDId - * @returns void - */ - deleteHeadsUpDisplay: function HS_deleteHeadsUpDisplay(aHUDId) - { - delete this.hudReferences[aHUDId]; - }, - /** * Register a new Heads Up Display * - * @param nsIDOMWindow aContentWindow * @returns void */ - registerDisplay: function HS_registerDisplay(aHUDId, aContentWindow) + registerDisplay: function HS_registerDisplay(aHUDId) { - // register a display DOM node Id and HUD uriSpec with the service - - if (!aHUDId || !aContentWindow){ + // register a display DOM node Id with the service. + if (!aHUDId){ throw new Error(ERRORS.MISSING_ARGS); } - var URISpec = aContentWindow.document.location.href; this.filterPrefs[aHUDId] = this.defaultFilterPrefs; - this.displayRegistry[aHUDId] = URISpec; - - this._headsUpDisplays[aHUDId] = { id: aHUDId }; - - this.registerActiveContext(aHUDId); // init storage objects: this.storage.createDisplay(aHUDId); - - var huds = this.uriRegistry[URISpec]; - var foundHUDId = false; - - if (huds) { - var len = huds.length; - for (var i = 0; i < len; i++) { - if (huds[i] == aHUDId) { - foundHUDId = true; - break; - } - } - if (!foundHUDId) { - this.uriRegistry[URISpec].push(aHUDId); - } - } - else { - this.uriRegistry[URISpec] = [aHUDId]; - } - - var windows = this.windowRegistry[aHUDId]; - if (!windows) { - this.windowRegistry[aHUDId] = [aContentWindow]; - } - else { - windows.push(aContentWindow); - } }, /** @@ -1662,7 +1613,7 @@ HUD_SERVICE.prototype = var id, outputNode; if (typeof(aHUD) === "string") { id = aHUD; - outputNode = this.mixins.getOutputNodeById(aHUD); + outputNode = this.getHeadsUpDisplay(aHUD); } else { id = aHUD.getAttribute("id"); @@ -1683,28 +1634,20 @@ HUD_SERVICE.prototype = // remove the DOM Nodes parent.removeChild(outputNode); - // remove our record of the DOM Nodes from the registry - delete this._headsUpDisplays[id]; // remove the HeadsUpDisplay object from memory - this.deleteHeadsUpDisplay(id); + delete this.hudReferences[id]; // remove the related storage object this.storage.removeDisplay(id); - // remove the related window objects - delete this.windowRegistry[id]; - let displays = this.displays(); - - var uri = this.displayRegistry[id]; - - if (this.uriRegistry[uri]) { - this.uriRegistry[uri] = this.uriRegistry[uri].filter(function(e) e != id); + for (let windowID in this.windowIds) { + if (this.windowIds[windowID] == id) { + delete this.windowIds[windowID]; + } } - delete displays[id]; - delete this.displayRegistry[id]; - delete this.uriRegistry[uri]; + this.unregisterActiveContext(id); - if (Object.keys(this._headsUpDisplays).length == 0) { + if (Object.keys(this.hudReferences).length == 0) { this.suspend(); } }, @@ -1717,7 +1660,7 @@ HUD_SERVICE.prototype = */ wakeup: function HS_wakeup() { - if (Object.keys(this._headsUpDisplays).length > 0) { + if (Object.keys(this.hudReferences).length > 0) { return; } @@ -1761,8 +1704,8 @@ HUD_SERVICE.prototype = */ shutdown: function HS_shutdown() { - for (var displayId in this._headsUpDisplays) { - this.unregisterDisplay(displayId); + for (let hudId in this.hudReferences) { + this.unregisterDisplay(hudId); } }, @@ -1775,84 +1718,52 @@ HUD_SERVICE.prototype = */ getHudIdByWindow: function HS_getHudIdByWindow(aContentWindow) { - // Fast path: check the cached window registry. - for (let hudId in this.windowRegistry) { - if (this.windowRegistry[hudId] && - this.windowRegistry[hudId].indexOf(aContentWindow) != -1) { - return hudId; - } - } - - // As a fallback, do a little pointer chasing to try to find the Web - // Console. This fallback approach occurs when opening the Console on a - // page with subframes. - let [ , tabBrowser, browser ] = ConsoleUtils.getParents(aContentWindow); - if (!tabBrowser) { - return null; - } - - let notificationBox = tabBrowser.getNotificationBox(browser); - let hudBox = notificationBox.querySelector(".hud-box"); - if (!hudBox) { - return null; - } - - // Cache it! - let hudId = hudBox.id; - this.windowRegistry[hudId].push(aContentWindow); - - let uri = aContentWindow.document.location.href; - if (!this.uriRegistry[uri]) { - this.uriRegistry[uri] = [ hudId ]; - } else { - this.uriRegistry[uri].push(hudId); - } - - return hudId; + let windowId = this.getWindowId(aContentWindow); + return this.getHudIdByWindowId(windowId); }, /** - * Gets HUD DOM Node + * Gets the Web Console DOM node, the .hud-box. + * * @param string id * The Heads Up Display DOM Id * @returns nsIDOMNode */ getHeadsUpDisplay: function HS_getHeadsUpDisplay(aId) { - return this.mixins.getOutputNodeById(aId); + return aId in this.hudReferences ? this.hudReferences[aId].HUDBox : null; }, /** - * gets the nsIDOMNode outputNode by ID via the gecko app mixins + * Gets the Web Console DOM node, the .hud-box. * * @param string aId * @returns nsIDOMNode */ getOutputNodeById: function HS_getOutputNodeById(aId) { - return this.mixins.getOutputNodeById(aId); + return this.getHeadsUpDisplay(aId); }, /** - * Gets an object that contains active DOM Node Ids for all Heads Up Displays - * - * @returns object - */ - displays: function HS_displays() { - return this._headsUpDisplays; - }, - - /** - * Gets an array that contains active DOM Node Ids for all HUDs + * Gets an array that contains all the HUD IDs. * @returns array */ displaysIndex: function HS_displaysIndex() { - var props = []; - for (var prop in this._headsUpDisplays) { - props.push(prop); - } - return props; + return Object.keys(this.hudReferences); + }, + + /** + * Returns the hudId that is corresponding to the given outer window ID. + * + * @param number aWindowId + * the outer window ID + * @returns string the hudId + */ + getHudIdByWindowId: function HS_getHudIdByWindowId(aWindowId) + { + return this.windowIds[aWindowId]; }, /** @@ -1965,21 +1876,22 @@ HUD_SERVICE.prototype = severity = SEVERITY_WARNING; } - // Sends the error to all applicable Web Consoles. - let hudIds = ConsoleUtils.getHUDIdsForScriptError(aScriptError); - for (let i = 0; i < hudIds.length; i++) { - let hudId = hudIds[i]; - let outputNode = this.hudReferences[hudId].outputNode; - let chromeDocument = outputNode.ownerDocument; + let window = HUDService.getWindowByWindowId(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, - aCategory, - severity, - aScriptError.errorMessage, - aScriptError.sourceName, - aScriptError.lineNumber); + let node = ConsoleUtils.createMessageNode(chromeDocument, + aCategory, + severity, + aScriptError.errorMessage, + aScriptError.sourceName, + aScriptError.lineNumber); - ConsoleUtils.outputMessageNode(node, hudId); + ConsoleUtils.outputMessageNode(node, hudId); + } } }, @@ -2096,7 +2008,7 @@ HUD_SERVICE.prototype = } // Try to get the hudId that is associated to the window. - hudId = self.getHudIdByWindow(win); + hudId = self.getHudIdByWindow(win.top); if (!hudId) { return; } @@ -2561,7 +2473,7 @@ HUD_SERVICE.prototype = return; } - this.registerDisplay(hudId, aContentWindow); + this.registerDisplay(hudId); let hudNode; let childNodes = nBox.childNodes; @@ -2586,6 +2498,8 @@ HUD_SERVICE.prototype = hud = new HeadsUpDisplay(config); HUDService.registerHUDReference(hud); + let windowId = this.getWindowId(aContentWindow.top); + this.windowIds[windowId] = hudId; } else { hud = this.hudReferences[hudId]; @@ -4678,42 +4592,6 @@ function FirefoxApplicationHooks() { } FirefoxApplicationHooks.prototype = { - - /** - * Firefox-specific method for getting an array of chrome Window objects - */ - get chromeWindows() - { - var windows = []; - var enumerator = Services.ww.getWindowEnumerator(null); - while (enumerator.hasMoreElements()) { - windows.push(enumerator.getNext()); - } - return windows; - }, - - /** - * Firefox-specific method for getting the DOM node (per tab) that message - * nodes are appended to. - * @param aId - * The DOM node's id. - */ - getOutputNodeById: function FAH_getOutputNodeById(aId) - { - if (!aId) { - throw new Error("FAH_getOutputNodeById: id is null!!"); - } - var enumerator = Services.ww.getWindowEnumerator(null); - while (enumerator.hasMoreElements()) { - let window = enumerator.getNext(); - let node = window.document.getElementById(aId); - if (node) { - return node; - } - } - throw new Error("Cannot get outputNode by id"); - }, - /** * gets the current contentWindow (Firefox-specific) * @@ -4722,7 +4600,7 @@ FirefoxApplicationHooks.prototype = { getCurrentContext: function FAH_getCurrentContext() { return Services.wm.getMostRecentWindow("navigator:browser"); - } + }, }; ////////////////////////////////////////////////////////////////////////////// @@ -5052,79 +4930,6 @@ ConsoleUtils = { } return aSourceURL; - }, - - /** - * Given an instance of nsIScriptError, attempts to work out the IDs of HUDs - * to which the script should be sent. - * - * @param nsIScriptError aScriptError - * The script error that was received. - * @returns Array - */ - getHUDIdsForScriptError: - function ConsoleUtils_getHUDIdsForScriptError(aScriptError) { - if (aScriptError instanceof Ci.nsIScriptError2) { - let windowID = aScriptError.outerWindowID; - if (windowID) { - // We just need some arbitrary window here so that we can GI to - // nsIDOMWindowUtils... - let someWindow = Services.wm.getMostRecentWindow(null); - if (someWindow) { - let windowUtils = someWindow.QueryInterface(Ci.nsIInterfaceRequestor) - .getInterface(Ci.nsIDOMWindowUtils); - - // In the future (post-Electrolysis), getOuterWindowWithId() could - // return null, because the originating window could have gone away - // while we were in the process of receiving and/or processing a - // message. For future-proofing purposes, we do a null check here. - let content = windowUtils.getOuterWindowWithId(windowID); - if (content) { - let hudId = HUDService.getHudIdByWindow(content); - if (hudId) { - return [ hudId ]; - } - } - } - } - } - - // The error had no window ID. As a less precise fallback, see whether we - // can find some consoles to send to via the URI. - let hudIds = HUDService.uriRegistry[aScriptError.sourceName]; - return hudIds ? hudIds : []; - }, - - /** - * Returns the chrome window, the tab browser, and the browser that - * contain the given content window. - * - * NB: This function only works in Firefox. - * - * @param nsIDOMWindow aContentWindow - * The content window to query. If this parameter is not a content - * window, then [ null, null, null ] will be returned. - */ - getParents: function ConsoleUtils_getParents(aContentWindow) { - let chromeEventHandler = - aContentWindow.QueryInterface(Ci.nsIInterfaceRequestor) - .getInterface(Ci.nsIWebNavigation) - .QueryInterface(Ci.nsIDocShell) - .chromeEventHandler; - if (!chromeEventHandler) { - return [ null, null, null ]; - } - - let chromeWindow = chromeEventHandler.ownerDocument.defaultView; - let gBrowser = XPCNativeWrapper.unwrap(chromeWindow).gBrowser; - let documentElement = chromeWindow.document.documentElement; - if (!documentElement || !gBrowser || - documentElement.getAttribute("windowtype") !== "navigator:browser") { - // Not a browser window. - return [ chromeWindow, null, null ]; - } - - return [ chromeWindow, gBrowser, chromeEventHandler ]; } }; @@ -5692,8 +5497,11 @@ HUDConsoleObserver = { return; } - if (!(aSubject instanceof Ci.nsIScriptError)) + if (!(aSubject instanceof Ci.nsIScriptError) || + !(aSubject instanceof Ci.nsIScriptError2) || + !aSubject.outerWindowID) { return; + } switch (aSubject.category) { // We ignore chrome-originating errors as we only diff --git a/toolkit/components/console/hudservice/tests/browser/browser_webconsole_bug_581231_close_button.js b/toolkit/components/console/hudservice/tests/browser/browser_webconsole_bug_581231_close_button.js index d33c00e6d78..270f53549f4 100644 --- a/toolkit/components/console/hudservice/tests/browser/browser_webconsole_bug_581231_close_button.js +++ b/toolkit/components/console/hudservice/tests/browser/browser_webconsole_bug_581231_close_button.js @@ -35,7 +35,7 @@ function testCloseButton() { EventUtils.synthesizeMouse(closeButton, 0, 0, {}); executeSoon(function (){ - ok(!(hudId in HUDService.windowRegistry), "the console is closed when " + + ok(!(hudId in HUDService.hudReferences), "the console is closed when " + "the close button is pressed"); closeButton = null; finishTest(); diff --git a/toolkit/components/console/hudservice/tests/browser/browser_webconsole_display_accessors.js b/toolkit/components/console/hudservice/tests/browser/browser_webconsole_display_accessors.js index 359d25114cb..a87c6ed08ae 100644 --- a/toolkit/components/console/hudservice/tests/browser/browser_webconsole_display_accessors.js +++ b/toolkit/components/console/hudservice/tests/browser/browser_webconsole_display_accessors.js @@ -53,8 +53,6 @@ function testDisplayAccessors() { openConsole(); - var allHuds = HUDService.displays(); - ok(typeof allHuds == "object", "allHuds is an object"); var idx = HUDService.displaysIndex(); let hudId = idx[0]; diff --git a/toolkit/components/console/hudservice/tests/browser/browser_webconsole_registries.js b/toolkit/components/console/hudservice/tests/browser/browser_webconsole_registries.js index 73d87952fea..0155da4d7bd 100644 --- a/toolkit/components/console/hudservice/tests/browser/browser_webconsole_registries.js +++ b/toolkit/components/console/hudservice/tests/browser/browser_webconsole_registries.js @@ -57,12 +57,10 @@ function testRegistries() { ok(displaysIdx.length == 1, "one display id found"); var display = displaysIdx[0]; - var registry = HUDService.displayRegistry; - var uri = registry[display]; - ok(registry[display], "we have a URI: " + registry[display]); + ok(HUDService.hudReferences[display], "we have a HUD"); - var uriRegistry = HUDService.uriRegistry; - ok(uriRegistry[uri].length == 1, "uri registry is working"); + let windowID = HUDService.getWindowId(content); + is(HUDService.windowIds[windowID], display, "windowIds is working"); finishTest(); }