From cdfb24ae1155901c876fe1eb3c47a0601beea108 Mon Sep 17 00:00:00 2001 From: Mihai Sucan Date: Thu, 31 May 2012 13:30:56 +0300 Subject: [PATCH] Bug 673148 - (async-webconsole) Part 5 - HUDService.jsm cleanup; r=rcampbell f=jwalker --- .../devtools/webconsole/HUDService-content.js | 241 ++- browser/devtools/webconsole/HUDService.jsm | 1334 +++-------------- browser/devtools/webconsole/test/Makefile.in | 5 - .../browser_warn_user_about_replaced_api.js | 36 +- .../browser_webconsole_bug_580400_groups.js | 17 +- ...rowser_webconsole_bug_586388_select_all.js | 16 +- ...le_bug_595350_multiple_windows_and_tabs.js | 2 +- ...ser_webconsole_bug_597460_filter_scroll.js | 22 +- ...ser_webconsole_bug_598357_jsterm_output.js | 2 +- .../browser_webconsole_bug_601352_scroll.js | 6 +- ...r_webconsole_bug_613642_maintain_scroll.js | 6 +- ...wser_webconsole_bug_613642_prune_scroll.js | 4 +- ...ser_webconsole_bug_614793_jsterm_scroll.js | 2 +- ...rowser_webconsole_bug_644419_log_limits.js | 8 +- ...owser_webconsole_bug_663443_panel_title.js | 71 +- .../test/browser_webconsole_bug_678816.js | 62 - .../test/browser_webconsole_consoleonpage.js | 47 - .../test/browser_webconsole_hud_getters.js | 33 - .../test/browser_webconsole_registries.js | 30 - .../test/browser_webconsole_window_zombie.js | 6 +- .../test/test-bug-678816-content.js | 28 - 21 files changed, 530 insertions(+), 1448 deletions(-) delete mode 100644 browser/devtools/webconsole/test/browser_webconsole_bug_678816.js delete mode 100644 browser/devtools/webconsole/test/browser_webconsole_consoleonpage.js delete mode 100644 browser/devtools/webconsole/test/browser_webconsole_hud_getters.js delete mode 100644 browser/devtools/webconsole/test/browser_webconsole_registries.js delete mode 100644 browser/devtools/webconsole/test/test-bug-678816-content.js diff --git a/browser/devtools/webconsole/HUDService-content.js b/browser/devtools/webconsole/HUDService-content.js index 803a3fafea1..1648a388bf3 100644 --- a/browser/devtools/webconsole/HUDService-content.js +++ b/browser/devtools/webconsole/HUDService-content.js @@ -261,6 +261,8 @@ let Manager = { * to the remote process. * - NetworkMonitor - log all the network activity and send HAR-like * messages to the remote Web Console process. + * - LocationChange - log page location changes. See + * ConsoleProgressListener. * * @param string aFeature * One of the supported features. @@ -287,6 +289,11 @@ let Manager = { case "NetworkMonitor": NetworkMonitor.init(aMessage); break; + case "LocationChange": + ConsoleProgressListener.startMonitor(ConsoleProgressListener + .MONITOR_LOCATION_CHANGE); + ConsoleProgressListener.sendLocation(); + break; default: Cu.reportError("Web Console content: unknown feature " + aFeature); break; @@ -324,6 +331,10 @@ let Manager = { case "NetworkMonitor": NetworkMonitor.destroy(); break; + case "LocationChange": + ConsoleProgressListener.stopMonitor(ConsoleProgressListener + .MONITOR_LOCATION_CHANGE); + break; default: Cu.reportError("Web Console content: unknown feature " + aFeature); break; @@ -738,8 +749,18 @@ let JSTerm = { /** * Initialize the JavaScript terminal feature. + * + * @param object aMessage + * Options for JSTerm sent from the remote Web Console instance. This + * object holds the following properties: + * + * - notifyNonNativeConsoleAPI - boolean that tells if you want to be + * notified if the window.console API object in the page is not the + * native one (if the page overrides it). + * A "JSTerm:NonNativeConsoleAPI" message will be sent if this is the + * case. */ - init: function JST_init() + init: function JST_init(aMessage) { this._objectCache = {}; this._messageHandlers = { @@ -755,6 +776,13 @@ let JSTerm = { } this._createSandbox(); + + if (aMessage && aMessage.notifyNonNativeConsoleAPI) { + let consoleObject = WebConsoleUtils.unwrap(this.window).console; + if (!("__mozillaConsole__" in consoleObject)) { + Manager.sendMessage("JSTerm:NonNativeConsoleAPI", {}); + } + } }, /** @@ -1697,10 +1725,8 @@ let NetworkMonitor = { // Monitor file:// activity as well. if (aMessage && aMessage.monitorFileActivity) { - let webProgress = docShell.QueryInterface(Ci.nsIWebProgress); - this.progressListener = new ConsoleProgressListener(); - webProgress.addProgressListener(this.progressListener, - Ci.nsIWebProgress.NOTIFY_STATE_ALL); + ConsoleProgressListener.startMonitor(ConsoleProgressListener + .MONITOR_FILE_ACTIVITY); } }, @@ -2240,11 +2266,8 @@ let NetworkMonitor = { activityDistributor.removeObserver(this); - if (this.progressListener) { - let webProgress = docShell.QueryInterface(Ci.nsIWebProgress); - webProgress.removeProgressListener(this.progressListener); - delete this.progressListener; - } + ConsoleProgressListener.stopMonitor(ConsoleProgressListener + .MONITOR_FILE_ACTIVITY); delete this.openRequests; delete this.openResponses; @@ -2252,23 +2275,149 @@ let NetworkMonitor = { }; /** - * A WebProgressListener that listens for location changes. This progress - * listener is used to track file loads. When a file:// URI is loaded - * a "WebConsole:FileActivity" message is sent to the remote Web Console - * instance. The message JSON holds only one property: uri (the file URI). + * A WebProgressListener that listens for location changes. * - * @constructor + * This progress listener is used to track file loads and other kinds of + * location changes. + * + * When a file:// URI is loaded a "WebConsole:FileActivity" message is sent to + * the remote Web Console instance. The message JSON holds only one property: + * uri (the file URI). + * + * When the current page location changes a "WebConsole:LocationChange" message + * is sent. See ConsoleProgressListener.sendLocation() for details. */ -function ConsoleProgressListener() { } +let ConsoleProgressListener = { + /** + * Constant used for startMonitor()/stopMonitor() that tells you want to + * monitor file loads. + */ + MONITOR_FILE_ACTIVITY: 1, + + /** + * Constant used for startMonitor()/stopMonitor() that tells you want to + * monitor page location changes. + */ + MONITOR_LOCATION_CHANGE: 2, + + /** + * Tells if you want to monitor file activity. + * @private + * @type boolean + */ + _fileActivity: false, + + /** + * Tells if you want to monitor location changes. + * @private + * @type boolean + */ + _locationChange: false, + + /** + * Tells if the console progress listener is initialized or not. + * @private + * @type boolean + */ + _initialized: false, -ConsoleProgressListener.prototype = { QueryInterface: XPCOMUtils.generateQI([Ci.nsIWebProgressListener, Ci.nsISupportsWeakReference]), - onStateChange: function CPL_onStateChange(aProgress, aRequest, aState, - aStatus) + /** + * Initialize the ConsoleProgressListener. + * @private + */ + _init: function CPL__init() { - if (!_alive || !(aState & Ci.nsIWebProgressListener.STATE_START)) { + if (this._initialized) { + return; + } + + this._initialized = true; + let webProgress = docShell.QueryInterface(Ci.nsIWebProgress); + webProgress.addProgressListener(this, Ci.nsIWebProgress.NOTIFY_STATE_ALL); + }, + + /** + * Start a monitor/tracker related to the current nsIWebProgressListener + * instance. + * + * @param number aMonitor + * Tells what you want to track. Available constants: + * - this.MONITOR_FILE_ACTIVITY + * Track file loads. + * - this.MONITOR_LOCATION_CHANGE + * Track location changes for the top window. + */ + startMonitor: function CPL_startMonitor(aMonitor) + { + switch (aMonitor) { + case this.MONITOR_FILE_ACTIVITY: + this._fileActivity = true; + break; + case this.MONITOR_LOCATION_CHANGE: + this._locationChange = true; + break; + default: + throw new Error("HUDService-content: unknown monitor type " + + aMonitor + " for the ConsoleProgressListener!"); + } + this._init(); + }, + + /** + * Stop a monitor. + * + * @param number aMonitor + * Tells what you want to stop tracking. See this.startMonitor() for + * the list of constants. + */ + stopMonitor: function CPL_stopMonitor(aMonitor) + { + switch (aMonitor) { + case this.MONITOR_FILE_ACTIVITY: + this._fileActivity = false; + break; + case this.MONITOR_LOCATION_CHANGE: + this._locationChange = false; + break; + default: + throw new Error("HUDService-content: unknown monitor type " + + aMonitor + " for the ConsoleProgressListener!"); + } + + if (!this._fileActivity && !this._locationChange) { + this.destroy(); + } + }, + + onStateChange: + function CPL_onStateChange(aProgress, aRequest, aState, aStatus) + { + if (!_alive) { + return; + } + + if (this._fileActivity) { + this._checkFileActivity(aProgress, aRequest, aState, aStatus); + } + + if (this._locationChange) { + this._checkLocationChange(aProgress, aRequest, aState, aStatus); + } + }, + + /** + * Check if there is any file load, given the arguments of + * nsIWebProgressListener.onStateChange. If the state change tells that a file + * URI has been loaded, then the remote Web Console instance is notified. + * @private + */ + _checkFileActivity: + function CPL__checkFileActivity(aProgress, aRequest, aState, aStatus) + { + if (!(aState & Ci.nsIWebProgressListener.STATE_START)) { return; } @@ -2289,10 +2438,62 @@ ConsoleProgressListener.prototype = { Manager.sendMessage("WebConsole:FileActivity", {uri: uri.spec}); }, + /** + * Check if the current window.top location is changing, given the arguments + * of nsIWebProgressListener.onStateChange. If that is the case, the remote + * Web Console instance is notified. + * @private + */ + _checkLocationChange: + function CPL__checkLocationChange(aProgress, aRequest, aState, aStatus) + { + let isStop = aState & Ci.nsIWebProgressListener.STATE_STOP; + let isNetwork = aState & Ci.nsIWebProgressListener.STATE_IS_NETWORK; + let isWindow = aState & Ci.nsIWebProgressListener.STATE_IS_WINDOW; + + // Skip non-interesting states. + if (!isStop || !isNetwork || !isWindow || + aProgress.DOMWindow != Manager.window) { + return; + } + + this.sendLocation(); + }, + onLocationChange: function() {}, onStatusChange: function() {}, onProgressChange: function() {}, onSecurityChange: function() {}, + + /** + * Send the location of the current top window to the remote Web Console. + * A "WebConsole:LocationChange" message is sent. The JSON object holds two + * properties: location and title. + */ + sendLocation: function CPL_sendLocation() + { + let message = { + "location": Manager.window.location.href, + "title": Manager.window.document.title, + }; + Manager.sendMessage("WebConsole:LocationChange", message); + }, + + /** + * Destroy the ConsoleProgressListener. + */ + destroy: function CPL_destroy() + { + if (!this._initialized) { + return; + } + + this._initialized = false; + this._fileActivity = false; + this._locationChange = false; + let webProgress = docShell.QueryInterface(Ci.nsIWebProgress); + webProgress.removeProgressListener(this); + }, }; Manager.init(); diff --git a/browser/devtools/webconsole/HUDService.jsm b/browser/devtools/webconsole/HUDService.jsm index 405e67c7b1b..eefdf987f56 100644 --- a/browser/devtools/webconsole/HUDService.jsm +++ b/browser/devtools/webconsole/HUDService.jsm @@ -19,18 +19,6 @@ XPCOMUtils.defineLazyServiceGetter(this, "clipboardHelper", "@mozilla.org/widget/clipboardhelper;1", "nsIClipboardHelper"); -XPCOMUtils.defineLazyGetter(this, "gcli", function () { - var obj = {}; - Cu.import("resource:///modules/gcli.jsm", obj); - return obj.gcli; -}); - -XPCOMUtils.defineLazyGetter(this, "template", function () { - var obj = {}; - Cu.import("resource:///modules/devtools/Templater.jsm", obj); - return obj.template; -}); - XPCOMUtils.defineLazyModuleGetter(this, "PropertyPanel", "resource:///modules/PropertyPanel.jsm"); @@ -40,17 +28,6 @@ XPCOMUtils.defineLazyModuleGetter(this, "PropertyTreeView", XPCOMUtils.defineLazyModuleGetter(this, "AutocompletePopup", "resource:///modules/AutocompletePopup.jsm"); -XPCOMUtils.defineLazyGetter(this, "ScratchpadManager", function () { - var obj = {}; - try { - Cu.import("resource:///modules/devtools/scratchpad-manager.jsm", obj); - } - catch (err) { - Cu.reportError(err); - } - return obj.ScratchpadManager; -}); - XPCOMUtils.defineLazyModuleGetter(this, "NetworkPanel", "resource:///modules/NetworkPanel.jsm"); @@ -72,12 +49,6 @@ function LogFactory(aMessagePrefix) let log = LogFactory("*** HUDService:"); -const HUD_STRINGS_URI = "chrome://browser/locale/devtools/webconsole.properties"; - -XPCOMUtils.defineLazyGetter(this, "stringBundle", function () { - return Services.strings.createBundle(HUD_STRINGS_URI); -}); - // The amount of time in milliseconds that must pass between messages to // trigger the display of a new group. const NEW_GROUP_DELAY = 5000; @@ -300,16 +271,6 @@ function pruneConsoleOutputIfNecessary(aHUDId, aCategory) function HUD_SERVICE() { - // TODO: provide mixins for FENNEC: bug 568621 - if (appName() == "FIREFOX") { - var mixins = new FirefoxApplicationHooks(); - } - else { - throw new Error("Unsupported Application"); - } - - this.mixins = mixins; - // These methods access the "this" object, but they're registered as // event listeners. So we hammer in the "this" binding. this.onTabClose = this.onTabClose.bind(this); @@ -318,17 +279,6 @@ function HUD_SERVICE() // Remembers the last console height, in pixels. this.lastConsoleHeight = Services.prefs.getIntPref("devtools.hud.height"); - /** - * Collection of HUDIds that map to the tabs/windows/contexts - * that a HeadsUpDisplay can be activated for. - */ - this.activatedContexts = []; - - /** - * Collection of outer window IDs mapping to HUD IDs. - */ - this.windowIds = {}; - /** * Each HeadsUpDisplay has a set of filter preferences */ @@ -357,149 +307,87 @@ HUD_SERVICE.prototype = */ sequencer: null, - /** - * Tell the HUDService that a HeadsUpDisplay can be activated - * for the window or context that has 'aContextDOMId' node id - * - * @param string aContextDOMId - * @return void - */ - registerActiveContext: function HS_registerActiveContext(aContextDOMId) - { - this.activatedContexts.push(aContextDOMId); - }, - /** * Firefox-specific current tab getter * * @returns nsIDOMWindow */ currentContext: function HS_currentContext() { - return this.mixins.getCurrentContext(); - }, - - /** - * Tell the HUDService that a HeadsUpDisplay should be deactivated - * - * @param string aContextDOMId - * @return void - */ - unregisterActiveContext: function HS_deregisterActiveContext(aContextDOMId) - { - var domId = aContextDOMId.split("_")[1]; - var idx = this.activatedContexts.indexOf(domId); - if (idx > -1) { - this.activatedContexts.splice(idx, 1); - } - }, - - /** - * Tells callers that a HeadsUpDisplay can be activated for the context - * - * @param string aContextDOMId - * @return boolean - */ - canActivateContext: function HS_canActivateContext(aContextDOMId) - { - var domId = aContextDOMId.split("_")[1]; - for (var idx in this.activatedContexts) { - if (this.activatedContexts[idx] == domId){ - return true; - } - } - return false; + return Services.wm.getMostRecentWindow("navigator:browser"); }, /** * Activate a HeadsUpDisplay for the given tab context. * - * @param Element aContext the tab element. - * @param boolean aAnimated animate opening the Web Console? - * @returns void + * @param nsIDOMElement aTab + * The xul:tab element. + * @param boolean aAnimated + * True if you want to animate the opening of the Web console. + * @return object + * The new HeadsUpDisplay instance. */ - activateHUDForContext: function HS_activateHUDForContext(aContext, aAnimated) + activateHUDForContext: function HS_activateHUDForContext(aTab, aAnimated) { + let hudId = "hud_" + aTab.linkedPanel; + if (hudId in this.hudReferences) { + return this.hudReferences[hudId]; + } + this.wakeup(); - let window = aContext.linkedBrowser.contentWindow; - let chromeDocument = aContext.ownerDocument; - let nBox = chromeDocument.defaultView.getNotificationBox(window); - this.registerActiveContext(nBox.id); - this.windowInitializer(window); + let window = aTab.ownerDocument.defaultView; + let gBrowser = window.gBrowser; - let hudId = "hud_" + nBox.id; - let hudRef = this.hudReferences[hudId]; + // TODO: check that this works as intended + gBrowser.tabContainer.addEventListener("TabClose", this.onTabClose, false); + window.addEventListener("unload", this.onWindowUnload, false); - if (!aAnimated || hudRef.consolePanel) { + this.registerDisplay(hudId); + + let hud = new HeadsUpDisplay(aTab); + this.hudReferences[hudId] = hud; + + // register the controller to handle "select all" properly + this.createController(window); + + if (!aAnimated || hud.consolePanel) { this.disableAnimation(hudId); } - // Create a processing instruction for GCLIs CSS stylesheet, but only if - // we don't have one for this document. Also record the context we're - // adding this for so we know when to remove it. - let procInstr = aContext.ownerDocument.gcliCssProcInstr; - if (!procInstr) { - procInstr = aContext.ownerDocument.createProcessingInstruction( - "xml-stylesheet", - "href='chrome://browser/skin/devtools/gcli.css' type='text/css'"); - procInstr.contexts = []; - - let root = aContext.ownerDocument.getElementsByTagName('window')[0]; - root.parentNode.insertBefore(procInstr, root); - aContext.ownerDocument.gcliCssProcInstr = procInstr; - } - if (procInstr.contexts.indexOf(hudId) == -1) { - procInstr.contexts.push(hudId); - } HeadsUpDisplayUICommands.refreshCommand(); + + return hud; }, /** * Deactivate a HeadsUpDisplay for the given tab context. * - * @param nsIDOMWindow aContext - * @param aAnimated animate closing the web console? - * @returns void + * @param nsIDOMElement aTab + * The xul:tab element you want to enable the Web Console for. + * @param boolean aAnimated + * True if you want to animate the closing of the Web console. + * @return void */ - deactivateHUDForContext: function HS_deactivateHUDForContext(aContext, aAnimated) + deactivateHUDForContext: function HS_deactivateHUDForContext(aTab, aAnimated) { - let browser = aContext.linkedBrowser; - let window = browser.contentWindow; - let chromeDocument = aContext.ownerDocument; - let nBox = chromeDocument.defaultView.getNotificationBox(window); - let hudId = "hud_" + nBox.id; - let displayNode = chromeDocument.getElementById(hudId); - let hudFound = (hudId in this.hudReferences) && displayNode; - - if (hudFound) { - if (!aAnimated) { - this.storeHeight(hudId); - } - - this.unregisterDisplay(hudId); - - window.focus(); - HeadsUpDisplayUICommands.refreshCommand(); + let hudId = "hud_" + aTab.linkedPanel; + if (!(hudId in this.hudReferences)) { + return; } - // Remove this context from the list of contexts that need the GCLI CSS - // processing instruction and then remove the processing instruction if it - // isn't needed any more. - let procInstr = aContext.ownerDocument.gcliCssProcInstr; - if (procInstr) { - procInstr.contexts = procInstr.contexts.filter(function(id) { - return id !== hudId; - }); - if (procInstr.contexts.length == 0 && procInstr.parentNode) { - procInstr.parentNode.removeChild(procInstr); - delete aContext.ownerDocument.gcliCssProcInstr; - } + if (!aAnimated) { + this.storeHeight(hudId); } - if (hudFound) { - let id = WebConsoleUtils.supportsString(hudId); - Services.obs.notifyObservers(id, "web-console-destroyed", null); - } + this.unregisterDisplay(hudId); + + let contentWindow = aTab.linkedBrowser.contentWindow; + contentWindow.focus(); + + HeadsUpDisplayUICommands.refreshCommand(); + + let id = WebConsoleUtils.supportsString(hudId); + Services.obs.notifyObservers(id, "web-console-destroyed", null); }, /** @@ -697,15 +585,6 @@ HUD_SERVICE.prototype = this.regroupOutput(outputNode); }, - /** - * Register a reference of each HeadsUpDisplay that is created - */ - registerHUDReference: - function HS_registerHUDReference(aHUD) - { - this.hudReferences[aHUD.hudId] = aHUD; - }, - /** * Register a new Heads Up Display * @@ -741,53 +620,12 @@ HUD_SERVICE.prototype = unregisterDisplay: function HS_unregisterDisplay(aHUDId) { let hud = this.getHudReferenceById(aHUDId); - - // Remove children from the output. If the output is not cleared, there can - // be leaks as some nodes has node.onclick = function; set and GC can't - // remove the nodes then. - if (hud.gcliterm) { - hud.gcliterm.clearOutput(); - } - let document = hud.chromeDocument; hud.destroy(); - // Make sure that the console panel does not try to call - // deactivateHUDForContext() again. - hud.consoleWindowUnregisterOnHide = false; - - // Remove the HUDBox and the consolePanel if the Web Console is inside a - // floating panel. - if (hud.consolePanel && hud.consolePanel.parentNode) { - hud.consolePanel.hidePopup(); - hud.consolePanel.parentNode.removeChild(hud.consolePanel); - hud.consolePanel.removeAttribute("hudId"); - hud.consolePanel = null; - } - - hud.HUDBox.parentNode.removeChild(hud.HUDBox); - - if (hud.splitter.parentNode) { - hud.splitter.parentNode.removeChild(hud.splitter); - } - delete this.hudReferences[aHUDId]; - for (let windowID in this.windowIds) { - if (this.windowIds[windowID] == aHUDId) { - delete this.windowIds[windowID]; - } - } - - this.unregisterActiveContext(aHUDId); - - let popupset = document.getElementById("mainPopupSet"); - let panels = popupset.querySelectorAll("panel[hudId=" + aHUDId + "]"); - for (let i = 0; i < panels.length; i++) { - panels[i].hidePopup(); - } - if (Object.keys(this.hudReferences).length == 0) { let autocompletePopup = document. getElementById("webConsole_autocompletePopup"); @@ -795,6 +633,14 @@ HUD_SERVICE.prototype = autocompletePopup.parentNode.removeChild(autocompletePopup); } + let window = document.defaultView; + + window.removeEventListener("unload", this.onWindowUnload, false); + + let gBrowser = window.gBrowser; + let tabContainer = gBrowser.tabContainer; + tabContainer.removeEventListener("TabClose", this.onTabClose, false); + this.suspend(); } }, @@ -829,14 +675,14 @@ HUD_SERVICE.prototype = }, /** - * Shutdown all HeadsUpDisplays on xpcom-shutdown + * Shutdown all HeadsUpDisplays on quit-application-granted. * * @returns void */ shutdown: function HS_shutdown() { - for (let hudId in this.hudReferences) { - this.deactivateHUDForContext(this.hudReferences[hudId].tab, false); + for (let hud of this.hudReferences) { + this.deactivateHUDForContext(hud.tab, false); } }, @@ -861,8 +707,16 @@ HUD_SERVICE.prototype = */ getHudIdByWindow: function HS_getHudIdByWindow(aContentWindow) { - let windowId = WebConsoleUtils.getOuterWindowId(aContentWindow); - return this.getHudIdByWindowId(windowId); + let window = this.currentContext(); + let index = + window.gBrowser.getBrowserIndexForDocument(aContentWindow.document); + if (index == -1) { + return null; + } + + let tab = window.gBrowser.tabs[index]; + let hudId = "hud_" + tab.linkedPanel; + return hudId in this.hudReferences ? hudId : null; }, /** @@ -876,18 +730,6 @@ HUD_SERVICE.prototype = return aId in this.hudReferences ? this.hudReferences[aId] : null; }, - /** - * 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]; - }, - /** * Get the current filter string for the HeadsUpDisplay * @@ -911,50 +753,6 @@ HUD_SERVICE.prototype = this.adjustVisibilityOnSearchStringChange(hudId, aTextBoxNode.value); }, - /** - * Inform user that the Web Console API has been replaced by a script - * in a content page. - * - * @param string aHUDId - * The ID of the Web Console to which to send the message. - * @return void - */ - logWarningAboutReplacedAPI: - function HS_logWarningAboutReplacedAPI(aHUDId) - { - let hud = this.hudReferences[aHUDId]; - let chromeDocument = hud.HUDBox.ownerDocument; - let message = stringBundle.GetStringFromName("ConsoleAPIDisabled"); - let node = ConsoleUtils.createMessageNode(chromeDocument, CATEGORY_JS, - SEVERITY_WARNING, message, - aHUDId); - ConsoleUtils.outputMessageNode(node, aHUDId); - }, - - /** - * Register a Gecko app's specialized ApplicationHooks object - * - * @returns void or throws "UNSUPPORTED APPLICATION" error - */ - registerApplicationHooks: - function HS_registerApplications(aAppName, aHooksObject) - { - switch(aAppName) { - case "FIREFOX": - this.applicationHooks = aHooksObject; - return; - default: - throw new Error("MOZ APPLICATION UNSUPPORTED"); - } - }, - - /** - * Registry of ApplicationHooks used by specified Gecko Apps - * - * @returns Specific Gecko 'ApplicationHooks' Object/Mixin - */ - applicationHooks: null, - /** * Assign a function to this property to listen for every request that * completes. Used by unit tests. The callback takes one argument: the HTTP @@ -1060,104 +858,6 @@ HUD_SERVICE.prototype = } }, - /** - * windowInitializer - checks what Gecko app is running and inits the HUD - * - * @param nsIDOMWindow aContentWindow - * @returns void - */ - windowInitializer: function HS_WindowInitalizer(aContentWindow) - { - var xulWindow = aContentWindow.QueryInterface(Ci.nsIInterfaceRequestor) - .getInterface(Ci.nsIWebNavigation) - .QueryInterface(Ci.nsIDocShell) - .chromeEventHandler.ownerDocument.defaultView; - - let xulWindow = WebConsoleUtils.unwrap(xulWindow); - - let docElem = xulWindow.document.documentElement; - if (!docElem || docElem.getAttribute("windowtype") != "navigator:browser" || - !xulWindow.gBrowser) { - // Do not do anything unless we have a browser window. - // This may be a view-source window or other type of non-browser window. - return; - } - - let gBrowser = xulWindow.gBrowser; - - let _browser = gBrowser. - getBrowserForDocument(aContentWindow.top.document); - - // ignore newly created documents that don't belong to a tab's browser - if (!_browser) { - return; - } - - let nBox = gBrowser.getNotificationBox(_browser); - let nBoxId = nBox.getAttribute("id"); - let hudId = "hud_" + nBoxId; - let windowUI = nBox.ownerDocument.getElementById("console_window_" + hudId); - if (windowUI) { - // The Web Console popup is already open, no need to continue. - if (aContentWindow == aContentWindow.top) { - let hud = this.hudReferences[hudId]; - hud.reattachConsole(aContentWindow); - } - return; - } - - if (!this.canActivateContext(hudId)) { - return; - } - - xulWindow.addEventListener("unload", this.onWindowUnload, false); - gBrowser.tabContainer.addEventListener("TabClose", this.onTabClose, false); - - this.registerDisplay(hudId); - - let hudNode; - let childNodes = nBox.childNodes; - - for (let i = 0; i < childNodes.length; i++) { - let id = childNodes[i].getAttribute("id"); - // `id` is a string with the format "hud_". - if (id.split("_")[0] == "hud") { - hudNode = childNodes[i]; - break; - } - } - - let hud; - // If there is no HUD for this tab create a new one. - if (!hudNode) { - // get nBox object and call new HUD - let config = { parentNode: nBox, - contentWindow: aContentWindow.top - }; - - hud = new HeadsUpDisplay(config); - - HUDService.registerHUDReference(hud); - let windowId = WebConsoleUtils.getOuterWindowId(aContentWindow.top); - this.windowIds[windowId] = hudId; - } - else { - hud = this.hudReferences[hudId]; - if (aContentWindow == aContentWindow.top) { - // TODO: name change?? doesn't actually re-attach the console - hud.reattachConsole(aContentWindow); - } - } - - // Need to detect that the console component has been paved over. - let consoleObject = WebConsoleUtils.unwrap(aContentWindow).console; - if (!("__mozillaConsole__" in consoleObject)) - this.logWarningAboutReplacedAPI(hudId); - - // register the controller to handle "select all" properly - this.createController(xulWindow); - }, - /** * Adds the command controller to the XUL window if it's not already present. * @@ -1165,9 +865,9 @@ HUD_SERVICE.prototype = * The browser XUL window. * @returns void */ - createController: function HUD_createController(aWindow) + createController: function HS_createController(aWindow) { - if (aWindow.webConsoleCommandController == null) { + if (!aWindow.webConsoleCommandController) { aWindow.webConsoleCommandController = new CommandController(aWindow); aWindow.controllers.insertControllerAt(0, aWindow.webConsoleCommandController); @@ -1232,8 +932,8 @@ HUD_SERVICE.prototype = resetHeight: function HS_resetHeight(aHUDId) { let HUD = this.hudReferences[aHUDId]; - let innerHeight = HUD.contentWindow.innerHeight; - let chromeWindow = HUD.chromeDocument.defaultView; + let innerHeight = HUD.browser.clientHeight; + let chromeWindow = HUD.chromeWindow; if (!HUD.consolePanel) { let splitterStyle = chromeWindow.getComputedStyle(HUD.splitter, null); innerHeight += parseInt(splitterStyle.height) + @@ -1252,7 +952,8 @@ HUD_SERVICE.prototype = if ((innerHeight - height) < MINIMUM_PAGE_HEIGHT) { height = innerHeight - MINIMUM_PAGE_HEIGHT; } - else if (height < MINIMUM_CONSOLE_HEIGHT) { + + if (isNaN(height) || height < MINIMUM_CONSOLE_HEIGHT) { height = MINIMUM_CONSOLE_HEIGHT; } @@ -1328,100 +1029,21 @@ HUD_SERVICE.prototype = // HeadsUpDisplay ////////////////////////////////////////////////////////////////////////// -/* +/** * HeadsUpDisplay is an interactive console initialized *per tab* that * displays console log data as well as provides an interactive terminal to * manipulate the current tab's document content. - * */ -function HeadsUpDisplay(aConfig) + * + * @param nsIDOMElement aTab + * The xul:tab for which you want the HeadsUpDisplay object. + */ +function HeadsUpDisplay(aTab) { - // sample config: { parentNode: aDOMNode, - // // or - // parentNodeId: "myHUDParent123", - // - // placement: "appendChild" - // // or - // placement: "insertBefore", - // placementChildNodeIndex: 0, - // } - - this.HUDBox = null; - - if (aConfig.parentNode) { - // TODO: need to replace these DOM calls with internal functions - // that operate on each application's node structure - // better yet, we keep these functions in a "bridgeModule" or the HUDService - // to keep a registry of nodeGetters for each application - // see bug 568647 - this.parentNode = aConfig.parentNode; - this.notificationBox = aConfig.parentNode; - this.chromeDocument = aConfig.parentNode.ownerDocument; - this.contentWindow = aConfig.contentWindow; - this.uriSpec = aConfig.contentWindow.location.href; - this.hudId = "hud_" + aConfig.parentNode.getAttribute("id"); - } - else { - // parentNodeId is the node's id where we attach the HUD - // TODO: is the "navigator:browser" below used in all Gecko Apps? - // see bug 568647 - let windowEnum = Services.wm.getEnumerator("navigator:browser"); - let parentNode; - let contentDocument; - let contentWindow; - let chromeDocument; - - // TODO: the following part is still very Firefox specific - // see bug 568647 - - while (windowEnum.hasMoreElements()) { - let window = windowEnum.getNext(); - try { - let gBrowser = window.gBrowser; - let _browsers = gBrowser.browsers; - let browserLen = _browsers.length; - - for (var i = 0; i < browserLen; i++) { - var _notificationBox = gBrowser.getNotificationBox(_browsers[i]); - this.notificationBox = _notificationBox; - - if (_notificationBox.getAttribute("id") == aConfig.parentNodeId) { - this.parentNodeId = _notificationBox.getAttribute("id"); - this.hudId = "hud_" + this.parentNodeId; - - parentNode = _notificationBox; - - this.contentDocument = - _notificationBox.childNodes[0].contentDocument; - this.contentWindow = - _notificationBox.childNodes[0].contentWindow; - this.uriSpec = aConfig.contentWindow.location.href; - - this.chromeDocument = - _notificationBox.ownerDocument; - - break; - } - } - } - catch (ex) { - Cu.reportError(ex); - } - - if (parentNode) { - break; - } - } - if (!parentNode) { - throw new Error(this.ERRORS.PARENTNODE_NOT_FOUND); - } - this.parentNode = parentNode; - this.notificationBox = parentNode; - } - - // create textNode Factory: - this.textFactory = NodeFactory("text", "xul", this.chromeDocument); - + this.tab = aTab; + this.hudId = "hud_" + this.tab.linkedPanel; + this.chromeDocument = this.tab.ownerDocument; this.chromeWindow = this.chromeDocument.defaultView; + this.notificationBox = this.chromeDocument.getElementById(this.tab.linkedPanel); this.browser = this.tab.linkedBrowser; this.messageManager = this.browser.messageManager; @@ -1431,16 +1053,10 @@ function HeadsUpDisplay(aConfig) // create a panel dynamically and attach to the parentNode this.createHUD(); - this.HUDBox.lastTimestamp = 0; // create the JSTerm input element - this.createConsoleInput(this.contentWindow, this.consoleWrap, this.outputNode); - if (this.jsterm) { - this.jsterm.inputNode.focus(); - } - else if (this.gcliterm) { - this.gcliterm.inputNode.focus(); - } + this.jsterm = new JSTerm(this); + this.jsterm.inputNode.focus(); // A cache for tracking repeated CSS Nodes. this.cssNodes = {}; @@ -1460,10 +1076,13 @@ HeadsUpDisplay.prototype = { "WebConsole:CachedMessages", "WebConsole:PageError", "JSTerm:EvalResult", "JSTerm:AutocompleteProperties", "JSTerm:ClearOutput", "JSTerm:InspectObject", "WebConsole:NetworkActivity", - "WebConsole:FileActivity"], + "WebConsole:FileActivity", "WebConsole:LocationChange", + "JSTerm:NonNativeConsoleAPI"], consolePanel: null, + contentLocation: "", + /** * The nesting depth of the currently active console group. */ @@ -1502,27 +1121,6 @@ HeadsUpDisplay.prototype = { return this.chromeDocument.getElementById("mainPopupSet"); }, - /** - * Get the tab associated to the HeadsUpDisplay object. - */ - get tab() - { - // TODO: we should only keep a reference to the tab object and use - // getters to determine the rest of objects we need - the chrome window, - // document, etc. We should simplify the entire code to use only a single - // tab object ref. See bug 656231. - let tab = null; - let id = this.notificationBox.id; - Array.some(this.chromeDocument.defaultView.gBrowser.tabs, function(aTab) { - if (aTab.linkedPanel == id) { - tab = aTab; - return true; - } - }); - - return tab; - }, - /** * Create a panel to open the web console if it should float above * the content in its own window. @@ -1540,7 +1138,7 @@ HeadsUpDisplay.prototype = { catch (ex) {} if (width < 1) { - width = this.HUDBox.clientWidth || this.contentWindow.innerWidth; + width = this.HUDBox.clientWidth || this.chromeWindow.innerWidth; } let height = this.HUDBox.clientHeight; @@ -1596,12 +1194,7 @@ HeadsUpDisplay.prototype = { this.outputNode.ensureIndexIsVisible(lastIndex); } - if (this.jsterm) { - this.jsterm.inputNode.focus(); - } - if (this.gcliterm) { - this.gcliterm.inputNode.focus(); - } + this.jsterm.inputNode.focus(); }).bind(this); panel.addEventListener("popupshown", onPopupShown,false); @@ -1626,8 +1219,6 @@ HeadsUpDisplay.prototype = { // Are we destroying the HUD or repositioning it? if (this.consoleWindowUnregisterOnHide) { HUDService.deactivateHUDForContext(this.tab, false); - } else { - this.consoleWindowUnregisterOnHide = true; } }).bind(this); @@ -1680,7 +1271,7 @@ HeadsUpDisplay.prototype = { */ getPanelTitle: function HUD_getPanelTitle() { - return l10n.getFormatStr("webConsoleWindowTitleAndURL", [this.uriSpec]); + return l10n.getFormatStr("webConsoleWindowTitleAndURL", [this.contentLocation]); }, positions: { @@ -1779,9 +1370,6 @@ HeadsUpDisplay.prototype = { if (this.jsterm) { this.jsterm.inputNode.focus(); } - if (this.gcliterm) { - this.gcliterm.inputNode.focus(); - } }, /** @@ -1790,42 +1378,6 @@ HeadsUpDisplay.prototype = { */ jsterm: null, - /** - * The GcliTerm object that contains the console's GCLI - */ - gcliterm: null, - - /** - * creates and attaches the console input node - * - * @param nsIDOMWindow aWindow - * @returns void - */ - createConsoleInput: - function HUD_createConsoleInput(aWindow, aParentNode, aExistingConsole) - { - let usegcli = false; - try { - // usegcli = Services.prefs.getBoolPref("devtools.gcli.enable"); - } - catch (ex) {} - - if (appName() == "FIREFOX") { - if (!usegcli) { - let mixin = new JSTermFirefoxMixin(aParentNode, aExistingConsole); - this.jsterm = new JSTerm(this, mixin); - } - else { - this.gcliterm = new GcliTerm(aWindow, this.hudId, this.chromeDocument, - this.console, this.hintNode, this.consoleWrap); - aParentNode.appendChild(this.gcliterm.element); - } - } - else { - throw new Error("Unsupported Gecko Application"); - } - }, - /** * Display cached messages that may have been collected before the UI is * displayed. @@ -1869,30 +1421,6 @@ HeadsUpDisplay.prototype = { } }, - /** - * Re-attaches a console when the contentWindow is recreated - * - * @param nsIDOMWindow aContentWindow - * @returns void - */ - reattachConsole: function HUD_reattachConsole(aContentWindow) - { - this.contentWindow = aContentWindow; - this.contentDocument = this.contentWindow.document; - this.uriSpec = this.contentWindow.location.href; - - if (this.consolePanel) { - this.consolePanel.label = this.getPanelTitle(); - } - - if (this.gcliterm) { - this.gcliterm.reattachConsole(this.contentWindow, this.console); - } - else if (!this.jsterm) { - this.createConsoleInput(this.contentWindow, this.consoleWrap, this.outputNode); - } - }, - /** * Shortcut to make XUL nodes * @@ -1912,8 +1440,6 @@ HeadsUpDisplay.prototype = { */ makeHUDNodes: function HUD_makeHUDNodes() { - let self = this; - this.splitter = this.makeXULNode("splitter"); this.splitter.setAttribute("class", "hud-splitter"); @@ -1921,6 +1447,7 @@ HeadsUpDisplay.prototype = { this.HUDBox.setAttribute("id", this.hudId); this.HUDBox.setAttribute("class", "hud-box animated"); this.HUDBox.style.height = 0; + this.HUDBox.lastTimestamp = 0; let outerWrap = this.makeXULNode("vbox"); outerWrap.setAttribute("class", "hud-outer-wrapper"); @@ -1985,7 +1512,7 @@ HeadsUpDisplay.prototype = { this.HUDBox.lastTimestamp = 0; - this.jsTermParentNode = outerWrap; + this.jsTermParentNode = this.consoleWrap; this.HUDBox.appendChild(outerWrap); return this.HUDBox; @@ -2295,12 +1822,7 @@ HeadsUpDisplay.prototype = { let hudId = this.hudId; function HUD_clearButton_onCommand() { let hud = HUDService.getHudReferenceById(hudId); - if (hud.jsterm) { - hud.jsterm.clearOutput(true); - } - if (hud.gcliterm) { - hud.gcliterm.clearOutput(); - } + hud.jsterm.clearOutput(true); } let clearButton = this.makeXULNode("toolbarbutton"); @@ -2349,8 +1871,6 @@ HeadsUpDisplay.prototype = { uiInOwnWindow: false, - get console() { return this.contentWindow.wrappedJSObject.console; }, - /** * Logs a message to the Web Console that originates from the remote Web * Console instance. @@ -2670,6 +2190,19 @@ HeadsUpDisplay.prototype = { ConsoleUtils.outputMessageNode(outputNode, this.hudId); }, + /** + * Inform user that the Web Console API has been replaced by a script + * in a content page. + */ + logWarningAboutReplacedAPI: function HUD_logWarningAboutReplacedAPI() + { + let message = l10n.getStr("ConsoleAPIDisabled"); + let node = ConsoleUtils.createMessageNode(this.chromeDocument, CATEGORY_JS, + SEVERITY_WARNING, message, + this.hudId); + 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", @@ -2692,9 +2225,11 @@ HeadsUpDisplay.prototype = { }, this); let message = { - features: ["ConsoleAPI", "JSTerm", "PageError", "NetworkMonitor"], + features: ["ConsoleAPI", "JSTerm", "PageError", "NetworkMonitor", + "LocationChange"], cachedMessages: ["ConsoleAPI", "PageError"], NetworkMonitor: { monitorFileActivity: true }, + JSTerm: { notifyNonNativeConsoleAPI: true }, preferences: { "NetworkMonitor.saveRequestAndResponseBodies": this.saveRequestAndResponseBodies, @@ -2746,6 +2281,12 @@ HeadsUpDisplay.prototype = { case "WebConsole:FileActivity": this.logFileActivity(aMessage.json.uri); break; + case "WebConsole:LocationChange": + this.onLocationChange(aMessage.json); + break; + case "JSTerm:NonNativeConsoleAPI": + this.logWarningAboutReplacedAPI(); + break; } }, @@ -2818,7 +2359,6 @@ HeadsUpDisplay.prototype = { callback: aCallback, }; } - this.messageManager.sendAsyncMessage(aName, aMessage); }, @@ -2891,6 +2431,22 @@ HeadsUpDisplay.prototype = { } }, + /** + * Handler for the "WebConsole:LocationChange" message. If the Web Console is + * opened in a panel the panel title is updated. + * + * @param object aMessage + * The message received from the content script. It needs to hold two + * properties: location and title. + */ + onLocationChange: function HUD_onLocationChange(aMessage) + { + this.contentLocation = aMessage.location; + if (this.consolePanel) { + this.consolePanel.label = this.getPanelTitle(); + } + }, + /** * Make a link given an output element. * @@ -2944,8 +2500,33 @@ HeadsUpDisplay.prototype = { if (this.jsterm) { this.jsterm.destroy(); } - if (this.gcliterm) { - this.gcliterm.destroy(); + + // Make sure that the console panel does not try to call + // deactivateHUDForContext() again. + this.consoleWindowUnregisterOnHide = false; + + let popupset = this.chromeDocument.getElementById("mainPopupSet"); + let panels = popupset.querySelectorAll("panel[hudId=" + this.hudId + "]"); + for (let panel of panels) { + if (panel != this.consolePanel) { + panel.hidePopup(); + } + } + + // Remove the HUDBox and the consolePanel if the Web Console is inside a + // floating panel. + if (this.consolePanel && this.consolePanel.parentNode) { + this.consolePanel.hidePopup(); + this.consolePanel.parentNode.removeChild(this.consolePanel); + this.consolePanel = null; + } + + if (this.HUDBox.parentNode) { + this.HUDBox.parentNode.removeChild(this.HUDBox); + } + + if (this.splitter.parentNode) { + this.splitter.parentNode.removeChild(this.splitter); } delete this.asyncRequests; @@ -3002,17 +2583,12 @@ function NodeFactory(aFactoryType, ignored, aDocument) * @constructor * @param object aHud * The HeadsUpDisplay object that owns this JSTerm instance. - * @param object aMixin - * Gecko-app (or Jetpack) specific utility object */ -function JSTerm(aHud, aMixin) +function JSTerm(aHud) { - // attach the UI by appending to aParentNode - - this.application = appName(); this.hud = aHud; - this.mixins = aMixin; this.document = this.hud.chromeDocument; + this.parentNode = this.hud.jsTermParentNode; this.hudId = this.hud.hudId; @@ -3032,38 +2608,53 @@ JSTerm.prototype = { COMPLETE_BACKWARD: 1, COMPLETE_HINT_ONLY: 2, + /** + * Initialize the JSTerminal instance. + */ init: function JST_init() { - this.inputNode = this.mixins.inputNode; - this.outputNode = this.mixins.outputNode; - this.completeNode = this.mixins.completeNode; + this._generateUI(); this._keyPress = this.keyPress.bind(this); this._inputEventHandler = this.inputEventHandler.bind(this); - this.inputNode.addEventListener("keypress", - this._keyPress, false); - this.inputNode.addEventListener("input", - this._inputEventHandler, false); - this.inputNode.addEventListener("keyup", - this._inputEventHandler, false); + this.inputNode.addEventListener("keypress", this._keyPress, false); + this.inputNode.addEventListener("input", this._inputEventHandler, false); + this.inputNode.addEventListener("keyup", this._inputEventHandler, false); }, - get codeInputString() + /** + * Generate the JSTerminal UI. + * @private + */ + _generateUI: function JST__generateUI() { - return this.inputNode.value; - }, - - generateUI: function JST_generateUI() - { - this.mixins.generateUI(); - }, - - attachUI: function JST_attachUI() - { - this.mixins.attachUI(); + this.completeNode = this.hud.makeXULNode("textbox"); + this.completeNode.setAttribute("class", "jsterm-complete-node"); + this.completeNode.setAttribute("multiline", "true"); + this.completeNode.setAttribute("rows", "1"); + this.completeNode.setAttribute("tabindex", "-1"); + + this.inputNode = this.hud.makeXULNode("textbox"); + this.inputNode.setAttribute("class", "jsterm-input-node"); + this.inputNode.setAttribute("multiline", "true"); + this.inputNode.setAttribute("rows", "1"); + + let inputStack = this.hud.makeXULNode("stack"); + inputStack.setAttribute("class", "jsterm-stack-node"); + inputStack.setAttribute("flex", "1"); + inputStack.appendChild(this.completeNode); + inputStack.appendChild(this.inputNode); + + let term = this.hud.makeXULNode("hbox"); + term.setAttribute("class", "jsterm-input-container"); + term.setAttribute("style", "direction: ltr;"); + term.appendChild(inputStack); + + this.parentNode.appendChild(term); }, + get outputNode() this.hud.outputNode, /** * Asynchronously evaluate a string in the content process sandbox. @@ -3293,7 +2884,7 @@ JSTerm.prototype = { */ clearOutput: function JST_clearOutput(aClearStorage) { - let hud = HUDService.getHudReferenceById(this.hudId); + let hud = this.hud; hud.cssNodes = {}; let outputNode = hud.outputNode; @@ -3514,12 +3105,6 @@ JSTerm.prototype = { return true; }, - refocus: function JSTF_refocus() - { - this.inputNode.blur(); - this.inputNode.focus(); - }, - /** * Check if the caret is at a location that allows selecting the previous item * in history when the user presses the Up arrow key. @@ -3992,107 +3577,6 @@ JSTerm.prototype = { delete this.hud; delete this.autocompletePopup; delete this.document; - delete this.mixins; - }, -}; - -/** - * Generates and attaches the JS Terminal part of the Web Console, which - * essentially consists of the interactive JavaScript input facility. - * - * @param nsIDOMNode aParentNode - * The Web Console wrapper node. - * @param nsIDOMNode aExistingConsole - * The Web Console output node. - * @return void - */ -function JSTermFirefoxMixin(aParentNode, aExistingConsole) -{ - // aExisting Console is the existing outputNode to use in favor of - // creating a new outputNode - this is so we can just attach the inputNode to - // a normal HeadsUpDisplay console output, and re-use code. - this.parentNode = aParentNode; - this.existingConsoleNode = aExistingConsole; - - if (aParentNode.ownerDocument) { - this.xulElementFactory = - NodeFactory("xul", "xul", aParentNode.ownerDocument); - - this.textFactory = NodeFactory("text", "xul", aParentNode.ownerDocument); - this.generateUI(); - this.attachUI(); - } - else { - throw new Error("aParentNode should be a DOM node with an ownerDocument property "); - } -} - -JSTermFirefoxMixin.prototype = { - /** - * Generates and attaches the UI for an entire JS Workspace or - * just the input node used under the console output - * - * @returns void - */ - generateUI: function JSTF_generateUI() - { - this.completeNode = this.xulElementFactory("textbox"); - this.completeNode.setAttribute("class", "jsterm-complete-node"); - this.completeNode.setAttribute("multiline", "true"); - this.completeNode.setAttribute("rows", "1"); - this.completeNode.setAttribute("tabindex", "-1"); - - this.inputNode = this.xulElementFactory("textbox"); - this.inputNode.setAttribute("class", "jsterm-input-node"); - this.inputNode.setAttribute("multiline", "true"); - this.inputNode.setAttribute("rows", "1"); - - let inputStack = this.xulElementFactory("stack"); - inputStack.setAttribute("class", "jsterm-stack-node"); - inputStack.setAttribute("flex", "1"); - inputStack.appendChild(this.completeNode); - inputStack.appendChild(this.inputNode); - - if (this.existingConsoleNode == undefined) { - throw new Error("This can't happen"); - } - - this.outputNode = this.existingConsoleNode; - - this.term = this.xulElementFactory("hbox"); - this.term.setAttribute("class", "jsterm-input-container"); - this.term.setAttribute("style", "direction: ltr;"); - this.term.appendChild(inputStack); - }, - - get inputValue() - { - return this.inputNode.value; - }, - - attachUI: function JSTF_attachUI() - { - this.parentNode.appendChild(this.term); - } -}; - -/** - * Firefox-specific Application Hooks. - * Each Gecko-based application will need an object like this in - * order to use the Heads Up Display - */ -function FirefoxApplicationHooks() -{ } - -FirefoxApplicationHooks.prototype = { - /** - * gets the current contentWindow (Firefox-specific) - * - * @returns nsIDOMWindow - */ - getCurrentContext: function FAH_getCurrentContext() - { - return Services.wm.getMostRecentWindow("navigator:browser"); }, }; @@ -4104,7 +3588,6 @@ FirefoxApplicationHooks.prototype = { * ConsoleUtils: a collection of globally used functions * */ - ConsoleUtils = { /** * Flag to turn on and off scrolling. @@ -4650,8 +4133,8 @@ HeadsUpDisplayUICommands = { */ getOpenHUD: function UIC_getOpenHUD() { let chromeWindow = HUDService.currentContext(); - let contentWindow = chromeWindow.gBrowser.selectedBrowser.contentWindow; - return HUDService.getHudIdByWindow(contentWindow); + let hudId = "hud_" + chromeWindow.gBrowser.selectedTab.linkedPanel; + return hudId in HUDService.hudReferences ? hudId : null; }, /** @@ -4758,23 +4241,18 @@ let WebConsoleObserver = { init: function WCO_init() { - Services.obs.addObserver(this, "content-document-global-created", false); Services.obs.addObserver(this, "quit-application-granted", false); }, observe: function WCO_observe(aSubject, aTopic) { - if (aTopic == "content-document-global-created") { - HUDService.windowInitializer(aSubject); - } - else if (aTopic == "quit-application-granted") { + if (aTopic == "quit-application-granted") { HUDService.shutdown(); } }, uninit: function WCO_uninit() { - Services.obs.removeObserver(this, "content-document-global-created"); Services.obs.removeObserver(this, "quit-application-granted"); }, }; @@ -4869,407 +4347,7 @@ CommandController.prototype = { } }; -/////////////////////////////////////////////////////////////////////////// -// appName -/////////////////////////////////////////////////////////////////////////// - -/** - * Get the app's name so we can properly dispatch app-specific - * methods per API call - * @returns Gecko application name - */ -function appName() -{ - let APP_ID = Services.appinfo.QueryInterface(Ci.nsIXULRuntime).ID; - - let APP_ID_TABLE = { - "{ec8030f7-c20a-464f-9b0e-13a3a9e97384}": "FIREFOX" , - "{3550f703-e582-4d05-9a08-453d09bdfdc6}": "THUNDERBIRD", - "{a23983c0-fd0e-11dc-95ff-0800200c9a66}": "FENNEC" , - "{92650c4d-4b8e-4d2a-b7eb-24ecf4f6b63a}": "SEAMONKEY", - }; - - let name = APP_ID_TABLE[APP_ID]; - - if (name){ - return name; - } - throw new Error("appName: UNSUPPORTED APPLICATION UUID"); -} - XPCOMUtils.defineLazyGetter(this, "HUDService", function () { - try { - return new HUD_SERVICE(); - } - catch (ex) { - Cu.reportError(ex); - } + return new HUD_SERVICE(); }); -/////////////////////////////////////////////////////////////////////////// -// GcliTerm -/////////////////////////////////////////////////////////////////////////// - -/** - * Some commands need customization - this is how we get at them. - */ -let commandExports = undefined; - -/** - * GcliTerm - * - * Initialize GCLI by creating a set of startup options from the available - * properties. - * - * @param nsIDOMWindow aContentWindow - * The content window that we're providing as the context to commands - * @param string aHudId - * The HUD to which we should send console messages. - * @param nsIDOMDocument aDocument - * The DOM document from which to create nodes. - * @param object aConsole - * Console object to use within the GcliTerm. - * @param nsIDOMElement aHintNode - * The node to which we add GCLI's hints. - * @constructor - */ -function GcliTerm(aContentWindow, aHudId, aDocument, aConsole, aHintNode, aConsoleWrap) -{ - this.context = Cu.getWeakReference(aContentWindow); - this.hudId = aHudId; - this.document = aDocument; - this.console = aConsole; - this.hintNode = aHintNode; - this._window = this.context.get().QueryInterface(Ci.nsIDOMWindow); - - this.createUI(); - this.createSandbox(); - - this.gcliConsole = gcli._internal.createDisplay({ - contentDocument: aContentWindow.document, - chromeDocument: this.document, - outputDocument: this.document, - chromeWindow: this.document.defaultView, - - hintElement: this.hintNode, - inputElement: this.inputNode, - completeElement: this.completeNode, - backgroundElement: this.inputStack, - consoleWrap: aConsoleWrap, - - eval: this.evalInSandbox.bind(this), - - environment: { - chromeDocument: this.document, - contentDocument: aContentWindow.document - }, - - tooltipClass: 'gcliterm-tooltip', - - // Allow GCLI:Inputter to decide how and when to open a scratchpad window - scratchpad: { - shouldActivate: function Scratchpad_shouldActivate(aEvent) { - return aEvent.shiftKey && - aEvent.keyCode === Ci.nsIDOMKeyEvent.DOM_VK_RETURN; - }, - activate: function Scratchpad_activate(aValue) { - aValue = aValue.replace(/^\s*{\s*/, ''); - ScratchpadManager.openScratchpad({ text: aValue }); - return true; - }, - linkText: stringBundle.GetStringFromName('scratchpad.linkText') - }, - }); - - this.gcliConsole.onVisibilityChange.add(this.onVisibilityChange, this); - this.gcliConsole.onOutput.add(this.onOutput, this); -} - -GcliTerm.prototype = { - /** - * Show or remove the hint column from the display. - */ - onVisibilityChange: function GcliTerm_onVisibilityChange(ev) - { - if (ev.visible) { - this.hintNode.parentNode.hidden = false; - } - else { - let permaHint = false; - try { - permaHint = Services.prefs.getBoolPref("devtools.gcli.permaHint"); - } - catch (ex) {} - - if (!permaHint) { - this.hintNode.parentNode.hidden = true; - } - } - }, - - /** - * Destroy the GcliTerm object. Call this method to avoid memory leaks. - */ - destroy: function Gcli_destroy() - { - this.gcliConsole.onVisibilityChange.remove(this.onVisibilityChange, this); - this.gcliConsole.onOutput.remove(this.onOutput, this); - this.gcliConsole.destroy(); - - delete this.context; - delete this.document; - delete this.console; - delete this.hintNode; - delete this._window; - - delete this.sandbox; - delete this.element; - delete this.inputStack; - delete this.completeNode; - delete this.inputNode; - }, - - /** - * Re-attaches a console when the contentWindow is recreated. - * - * @param nsIDOMWindow aContentWindow - * The content window that we're providing as the context to commands - * @param object aConsole - * Console object to use within the GcliTerm. - */ - reattachConsole: function Gcli_reattachConsole(aContentWindow, aConsole) - { - this.context = Cu.getWeakReference(aContentWindow); - this.console = aConsole; - this.createSandbox(); - - this.gcliConsole.reattach({ - contentDocument: aContentWindow.document, - environment: { - chromeDocument: this.document, - contentDocument: aContentWindow.document - }, - }); - }, - - /** - * Generates and attaches the GCLI Terminal part of the Web Console, which - * essentially consists of the interactive JavaScript input facility. - */ - createUI: function Gcli_createUI() - { - this.element = this.document.createElement("vbox"); - this.element.setAttribute("class", "gcliterm-input-container"); - this.element.setAttribute("flex", "0"); - - this.inputStack = this.document.createElement("stack"); - this.inputStack.setAttribute("class", "gcliterm-stack-node"); - this.element.appendChild(this.inputStack); - - this.completeNode = this.document.createElementNS(HTML_NS, "div"); - this.completeNode.setAttribute("class", "gcliterm-complete-node"); - this.completeNode.setAttribute("aria-live", "polite"); - this.inputStack.appendChild(this.completeNode); - - this.inputNode = this.document.createElement("textbox"); - this.inputNode.setAttribute("class", "gcliterm-input-node"); - this.inputNode.setAttribute("rows", "1"); - this.inputStack.appendChild(this.inputNode); - }, - - /** - * Called by GCLI/canon when command line output changes. - */ - onOutput: function Gcli_onOutput(aEvent) - { - // When we can update the history of the console, then we should stop - // filtering incomplete reports. - if (!aEvent.output.completed) { - return; - } - - this.writeOutput(aEvent.output.typed, CATEGORY_INPUT); - - // This is an experiment to see how much people yell when we stop reporting - // undefined replies. - if (aEvent.output.output === undefined) { - return; - } - - let output = aEvent.output.output; - let declaredType = aEvent.output.command.returnType || ""; - - if (declaredType == "object") { - let actualType = typeof output; - if (output === null) { - output = "null"; - } - else if (actualType == "string") { - output = "\"" + output + "\""; - } - else if (actualType == "object" || actualType == "function") { - let formatOpts = [ nameObject(output) ]; - output = stringBundle.formatStringFromName('gcliterm.instanceLabel', - formatOpts, formatOpts.length); - let linkNode = this.document.createElementNS(HTML_NS, 'html:span'); - linkNode.appendChild(this.document.createTextNode(output)); - linkNode.classList.add("hud-clickable"); - linkNode.setAttribute("aria-haspopup", "true"); - - // Make the object bring up the property panel. - linkNode.addEventListener("mousedown", function(aEv) { - this._startX = aEv.clientX; - this._startY = aEv.clientY; - }.bind(this), false); - - linkNode.addEventListener("click", function(aEv) { - if (aEv.detail != 1 || aEv.button != 0 || - (this._startX != aEv.clientX && this._startY != aEv.clientY)) { - return; - } - - if (!this._panelOpen) { - let propPanel = this.openPropertyPanel(aEvent.output.typed, aEvent.output.output, this); - propPanel.panel.setAttribute("hudId", this.hudId); - this._panelOpen = true; - } - }.bind(this), false); - - output = linkNode; - } - // else if (actualType == number/boolean/undefined) do nothing - } - - if (declaredType == "html" && typeof output == "string") { - output = this.document.createRange().createContextualFragment( - '
' + - output + '
'); - } - - // See https://github.com/mozilla/domtemplate/blob/master/README.md - // for docs on the template() function - let element = this.document.createRange().createContextualFragment( - '' + - ' ').firstChild; - - let hud = HUDService.getHudReferenceById(this.hudId); - let timestamp = Date.now(); - template(element, { - iconContainerStyle: "margin-left=" + (hud.groupDepth * GROUP_INDENT) + "px", - output: output, - timestamp: timestamp, - timestampString: l10n.timestampString(timestamp), - clipboardText: output.innerText, - id: "console-msg-" + HUDService.sequenceId() - }); - - ConsoleUtils.setMessageType(element, CATEGORY_OUTPUT, SEVERITY_LOG); - ConsoleUtils.outputMessageNode(element, this.hudId); - }, - - /** - * Setup the eval sandbox, should be called whenever we are attached. - */ - createSandbox: function Gcli_createSandbox() - { - // create a JS Sandbox out of this.context - this.sandbox = new Cu.Sandbox(this._window, { - sandboxPrototype: this._window, - wantXrays: false - }); - this.sandbox.console = this.console; - - JSTermHelper(this); - }, - - /** - * Evaluates a string in the sandbox. - * - * @param string aString - * String to evaluate in the sandbox - * @return The result of the evaluation - */ - evalInSandbox: function Gcli_evalInSandbox(aString) - { - let window = WebConsoleUtils.unwrap(this.sandbox.window); - let temp$ = null; - let temp$$ = null; - - // We prefer to execute the page-provided implementations for the $() and - // $$() functions. - if (typeof window.$ == "function") { - temp$ = this.sandbox.$; - delete this.sandbox.$; - } - if (typeof window.$$ == "function") { - temp$$ = this.sandbox.$$; - delete this.sandbox.$$; - } - - let result = Cu.evalInSandbox(aString, this.sandbox, "1.8", "Web Console", 1); - - if (temp$) { - this.sandbox.$ = temp$; - } - if (temp$$) { - this.sandbox.$$ = temp$$; - } - - return result; - }, - - /** - * Writes a message to the HUD that originates from the interactive - * JavaScript console. - * - * @param string aOutputMessage - * The message to display. - * @param number aCategory - * One of the CATEGORY_ constants. - * @param number aSeverity - * One of the SEVERITY_ constants. - */ - writeOutput: function Gcli_writeOutput(aOutputMessage, aCategory, aSeverity, aOptions) - { - aOptions = aOptions || {}; - - let node = ConsoleUtils.createMessageNode( - this.document, - aCategory || CATEGORY_OUTPUT, - aSeverity || SEVERITY_LOG, - aOutputMessage, - this.hudId, - aOptions.sourceUrl || undefined, - aOptions.sourceLine || undefined, - aOptions.clipboardText || undefined); - - ConsoleUtils.outputMessageNode(node, this.hudId); - }, - - clearOutput: JSTerm.prototype.clearOutput, - openPropertyPanel: JSTerm.prototype.openPropertyPanel, - - formatResult: WebConsoleUtils.formatResult, - getResultType: WebConsoleUtils.getResultType, - formatString: WebConsoleUtils.formatResultString, -}; - -/** - * A fancy version of toString() - */ -function nameObject(aObj) { - if (aObj.constructor && aObj.constructor.name) { - return aObj.constructor.name; - } - // If that fails, use Objects toString which sometimes gives something - // better than 'Object', and at least defaults to Object if nothing better - return Object.prototype.toString.call(aObj).slice(8, -1); -} diff --git a/browser/devtools/webconsole/test/Makefile.in b/browser/devtools/webconsole/test/Makefile.in index 4919f9fe154..535c868d028 100644 --- a/browser/devtools/webconsole/test/Makefile.in +++ b/browser/devtools/webconsole/test/Makefile.in @@ -25,12 +25,10 @@ _BROWSER_TEST_FILES = \ browser_webconsole_bug_597136_network_requests_from_chrome.js \ browser_webconsole_completion.js \ browser_webconsole_console_logging_api.js \ - browser_webconsole_consoleonpage.js \ browser_webconsole_chrome.js \ browser_webconsole_execution_scope.js \ browser_webconsole_for_of.js \ browser_webconsole_history.js \ - browser_webconsole_hud_getters.js \ browser_webconsole_js_input_and_output_styling.js \ browser_webconsole_js_input_expansion.js \ browser_webconsole_live_filtering_of_message_types.js \ @@ -46,7 +44,6 @@ _BROWSER_TEST_FILES = \ browser_webconsole_output_order.js \ browser_webconsole_property_panel.js \ browser_webconsole_property_provider.js \ - browser_webconsole_registries.js \ browser_webconsole_bug_587617_output_copy.js \ browser_webconsole_bug_585237_line_limit.js \ browser_webconsole_bug_581231_close_button.js \ @@ -105,7 +102,6 @@ _BROWSER_TEST_FILES = \ browser_webconsole_bug_651501_document_body_autocomplete.js \ browser_webconsole_bug_653531_highlighter_console_helper.js \ browser_webconsole_bug_659907_console_dir.js \ - browser_webconsole_bug_678816.js \ browser_webconsole_bug_664131_console_group.js \ browser_webconsole_bug_704295.js \ browser_webconsole_bug_658368_time_methods.js \ @@ -180,7 +176,6 @@ _BROWSER_TEST_PAGES = \ test-bug-644419-log-limits.html \ test-bug-632275-getters.html \ test-bug-646025-console-file-location.html \ - test-bug-678816-content.js \ test-file-location.js \ test-bug-658368-time-methods.html \ test-webconsole-error-observer.html \ diff --git a/browser/devtools/webconsole/test/browser_warn_user_about_replaced_api.js b/browser/devtools/webconsole/test/browser_warn_user_about_replaced_api.js index 75df03114c1..60f74266611 100644 --- a/browser/devtools/webconsole/test/browser_warn_user_about_replaced_api.js +++ b/browser/devtools/webconsole/test/browser_warn_user_about_replaced_api.js @@ -10,29 +10,39 @@ function test() { // First test that the warning does not appear on a normal page (about:blank) addTab("about:blank"); - browser.addEventListener("load", function() { - browser.removeEventListener("load", arguments.callee, true); + browser.addEventListener("load", function onLoad() { + browser.removeEventListener("load", onLoad, true); testOpenWebConsole(false); - executeSoon(testWarningPresent); }, true); } function testWarningPresent() { // Then test that the warning does appear on a page that replaces the API - browser.addEventListener("load", function() { - browser.removeEventListener("load", arguments.callee, true); + browser.addEventListener("load", function onLoad() { + browser.removeEventListener("load", onLoad, true); testOpenWebConsole(true); - finishTest(); }, true); browser.contentWindow.location = TEST_REPLACED_API_URI; } function testOpenWebConsole(shouldWarn) { - openConsole(); - - hud = HUDService.getHudByWindow(content); - ok(hud, "WebConsole was opened"); - - let msg = (shouldWarn ? "found" : "didn't find") + " API replacement warning"; - testLogEntry(hud.outputNode, "disabled", msg, false, !shouldWarn); + openConsole(null, function(hud) { + waitForSuccess({ + name: (shouldWarn ? "no " : "") + "API replacement warning", + validatorFn: function() + { + let pos = hud.outputNode.textContent.indexOf("disabled by"); + return shouldWarn ? pos > -1 : pos == -1; + }, + successFn: function() { + if (shouldWarn) { + finishTest(); + } + else { + closeConsole(null, testWarningPresent); + } + }, + failureFn: finishTest, + }); + }); } diff --git a/browser/devtools/webconsole/test/browser_webconsole_bug_580400_groups.js b/browser/devtools/webconsole/test/browser_webconsole_bug_580400_groups.js index 62ee17a2d5f..9d94721b55b 100644 --- a/browser/devtools/webconsole/test/browser_webconsole_bug_580400_groups.js +++ b/browser/devtools/webconsole/test/browser_webconsole_bug_580400_groups.js @@ -9,17 +9,15 @@ const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/te function test() { addTab(TEST_URI); - browser.addEventListener("DOMContentLoaded", testGroups, false); + browser.addEventListener("load", function onLoad() { + browser.removeEventListener("load", onLoad, true); + openConsole(null, testGroups); + }, true); } -function testGroups() { - browser.removeEventListener("DOMContentLoaded", testGroups, false); - - openConsole(); - - let HUD = HUDService.getHudByWindow(content); +function testGroups(HUD) { let jsterm = HUD.jsterm; - let outputNode = jsterm.outputNode; + let outputNode = HUD.outputNode; // We test for one group by testing for zero "new" groups. The // "webconsole-new-group" class creates a divider. Thus one group is @@ -46,9 +44,6 @@ function testGroups() { is(outputNode.querySelectorAll(".webconsole-new-group").length, 1, "one group divider exists after the third console message"); - jsterm.clearOutput(); - jsterm.history.splice(0, jsterm.history.length); // workaround for bug 592552 - finishTest(); } diff --git a/browser/devtools/webconsole/test/browser_webconsole_bug_586388_select_all.js b/browser/devtools/webconsole/test/browser_webconsole_bug_586388_select_all.js index fbd1eafb467..2e837bad8b2 100644 --- a/browser/devtools/webconsole/test/browser_webconsole_bug_586388_select_all.js +++ b/browser/devtools/webconsole/test/browser_webconsole_bug_586388_select_all.js @@ -12,16 +12,14 @@ const TEST_URI = "http://example.com/"; function test() { addTab(TEST_URI); - browser.addEventListener("DOMContentLoaded", - testSelectionWhenMovingBetweenBoxes, false); + browser.addEventListener("load", function onLoad() { + browser.removeEventListener("load", onLoad, true); + openConsole(null, testSelectionWhenMovingBetweenBoxes); + }, true); } -function testSelectionWhenMovingBetweenBoxes() { - browser.removeEventListener("DOMContentLoaded", - testSelectionWhenMovingBetweenBoxes, false); - openConsole(); - - let jsterm = HUDService.getHudByWindow(content).jsterm; +function testSelectionWhenMovingBetweenBoxes(hud) { + let jsterm = hud.jsterm; // Fill the console with some output. jsterm.clearOutput(); @@ -29,7 +27,7 @@ function testSelectionWhenMovingBetweenBoxes() { jsterm.execute("3 + 4"); jsterm.execute("5 + 6"); - outputNode = jsterm.outputNode; + let outputNode = hud.outputNode; ok(outputNode.childNodes.length >= 3, "the output node has children after " + "executing some JavaScript"); 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 fd807a93838..e1a57909042 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 @@ -57,7 +57,7 @@ function openConsoles() { let tab = openTabs[i]; openConsole(tab, function(index, hud) { ok(hud, "HUD is open for tab " + index); - hud.console.log("message for tab " + index); + hud.browser.contentWindow.console.log("message for tab " + index); consolesOpen++; }.bind(null, i)); } diff --git a/browser/devtools/webconsole/test/browser_webconsole_bug_597460_filter_scroll.js b/browser/devtools/webconsole/test/browser_webconsole_bug_597460_filter_scroll.js index 279a6156278..55bddd93df4 100644 --- a/browser/devtools/webconsole/test/browser_webconsole_bug_597460_filter_scroll.js +++ b/browser/devtools/webconsole/test/browser_webconsole_bug_597460_filter_scroll.js @@ -10,20 +10,15 @@ const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/test-network.html"; -function tabLoad(aEvent) { - browser.removeEventListener(aEvent.type, arguments.callee, true); - - openConsole(); - - let hudId = HUDService.getHudIdByWindow(content); - hud = HUDService.hudReferences[hudId]; +function consoleOpened(aHud) { + hud = aHud; for (let i = 0; i < 200; i++) { - hud.console.log("test message " + i); + content.console.log("test message " + i); } - HUDService.setFilterState(hudId, "network", false); - HUDService.setFilterState(hudId, "networkinfo", false); + HUDService.setFilterState(hud.hudId, "network", false); + HUDService.setFilterState(hud.hudId, "networkinfo", false); hud.filterBox.value = "test message"; HUDService.updateFilterText(hud.filterBox); @@ -36,7 +31,7 @@ function tabLoad(aEvent) { } function tabReload(aEvent) { - browser.removeEventListener(aEvent.type, arguments.callee, true); + browser.removeEventListener(aEvent.type, tabReload, true); let msgNode = hud.outputNode.querySelector(".webconsole-msg-network"); ok(msgNode, "found network message"); @@ -62,6 +57,9 @@ function tabReload(aEvent) { function test() { addTab(TEST_URI); - 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_598357_jsterm_output.js b/browser/devtools/webconsole/test/browser_webconsole_bug_598357_jsterm_output.js index 736ba44ee07..682eecfbb8d 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 @@ -141,7 +141,7 @@ function testGen() { // Ugly but it does the job. with (content) { - eval("HUD.console.log(" + consoleTest + ")"); + eval("content.console.log(" + consoleTest + ")"); } waitForSuccess({ 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 c080b19f0f0..591fcb5b312 100644 --- a/browser/devtools/webconsole/test/browser_webconsole_bug_601352_scroll.js +++ b/browser/devtools/webconsole/test/browser_webconsole_bug_601352_scroll.js @@ -17,13 +17,13 @@ function consoleOpened(HUD) { } for (let i = 0; i < 50; i++) { - HUD.console.log("test message " + i); + content.console.log("test message " + i); } - HUD.console.log(longMessage); + content.console.log(longMessage); for (let i = 0; i < 50; i++) { - HUD.console.log("test message " + i); + content.console.log("test message " + i); } HUD.jsterm.execute("1+1"); diff --git a/browser/devtools/webconsole/test/browser_webconsole_bug_613642_maintain_scroll.js b/browser/devtools/webconsole/test/browser_webconsole_bug_613642_maintain_scroll.js index 29a3904f50e..b3317a66921 100644 --- a/browser/devtools/webconsole/test/browser_webconsole_bug_613642_maintain_scroll.js +++ b/browser/devtools/webconsole/test/browser_webconsole_bug_613642_maintain_scroll.js @@ -19,7 +19,7 @@ function testGen() { let scrollBox = outputNode.scrollBoxObject.element; for (let i = 0; i < 150; i++) { - hud.console.log("test message " + i); + content.console.log("test message " + i); } waitForSuccess({ @@ -46,7 +46,7 @@ function testGen() { isnot(topPosition, oldScrollTop, "scroll location updated (moved to top)"); // add a message and make sure scroll doesn't change - hud.console.log("test message 150"); + content.console.log("test message 150"); waitForSuccess({ name: "console.log message no. 151 displayed", @@ -68,7 +68,7 @@ function testGen() { oldScrollTop = outputNode.scrollTop; - hud.console.log("test message 151"); + content.console.log("test message 151"); waitForSuccess({ name: "console.log message no. 152 displayed", diff --git a/browser/devtools/webconsole/test/browser_webconsole_bug_613642_prune_scroll.js b/browser/devtools/webconsole/test/browser_webconsole_bug_613642_prune_scroll.js index b0c60922671..5bde4960282 100644 --- a/browser/devtools/webconsole/test/browser_webconsole_bug_613642_prune_scroll.js +++ b/browser/devtools/webconsole/test/browser_webconsole_bug_613642_prune_scroll.js @@ -24,7 +24,7 @@ function testGen() { let boxObject = outputNode.scrollBoxObject; for (let i = 0; i < 150; i++) { - hud.console.log("test message " + i); + content.console.log("test message " + i); } waitForSuccess({ @@ -57,7 +57,7 @@ function testGen() { oldScrollTop = scrollBoxElement.scrollTop; // add a message - hud.console.log("hello world"); + content.console.log("hello world"); waitForSuccess({ name: "console.log message #151 displayed", diff --git a/browser/devtools/webconsole/test/browser_webconsole_bug_614793_jsterm_scroll.js b/browser/devtools/webconsole/test/browser_webconsole_bug_614793_jsterm_scroll.js index a883cc5c1a4..dd209380665 100644 --- a/browser/devtools/webconsole/test/browser_webconsole_bug_614793_jsterm_scroll.js +++ b/browser/devtools/webconsole/test/browser_webconsole_bug_614793_jsterm_scroll.js @@ -14,7 +14,7 @@ function consoleOpened(hud) { let boxObject = outputNode.scrollBoxObject.element; for (let i = 0; i < 150; i++) { - hud.console.log("test message " + i); + content.console.log("test message " + i); } waitForSuccess({ diff --git a/browser/devtools/webconsole/test/browser_webconsole_bug_644419_log_limits.js b/browser/devtools/webconsole/test/browser_webconsole_bug_644419_log_limits.js index cf72dd13eb4..017b3f90151 100644 --- a/browser/devtools/webconsole/test/browser_webconsole_bug_644419_log_limits.js +++ b/browser/devtools/webconsole/test/browser_webconsole_bug_644419_log_limits.js @@ -52,7 +52,7 @@ function testWebDevLimits(aEvent) { function testWebDevLimits2() { // Fill the log with Web Developer errors. for (let i = 0; i < 11; i++) { - hud.console.log("test message " + i); + content.console.log("test message " + i); } waitForSuccess({ @@ -80,7 +80,7 @@ function testJsLimits() { Services.prefs.setIntPref("devtools.hud.loglimit.exception", 10); hud.jsterm.clearOutput(); - hud.console.log("testing JS limits"); + content.console.log("testing JS limits"); // Find the sentinel entry. waitForSuccess({ @@ -131,7 +131,7 @@ function testNetLimits() { Services.prefs.setIntPref("devtools.hud.loglimit.network", 10); hud.jsterm.clearOutput(); - hud.console.log("testing Net limits"); + content.console.log("testing Net limits"); // Find the sentinel entry. waitForSuccess({ @@ -176,7 +176,7 @@ function testCssLimits() { Services.prefs.setIntPref("devtools.hud.loglimit.cssparser", 10); hud.jsterm.clearOutput(); - hud.console.log("testing CSS limits"); + content.console.log("testing CSS limits"); // Find the sentinel entry. waitForSuccess({ diff --git a/browser/devtools/webconsole/test/browser_webconsole_bug_663443_panel_title.js b/browser/devtools/webconsole/test/browser_webconsole_bug_663443_panel_title.js index 25f18f7567f..b485165d706 100644 --- a/browser/devtools/webconsole/test/browser_webconsole_bug_663443_panel_title.js +++ b/browser/devtools/webconsole/test/browser_webconsole_bug_663443_panel_title.js @@ -5,46 +5,53 @@ const TEST_URI = "data:text/html;charset=utf-8,

test for bug 663443. test1"; const POSITION_PREF = "devtools.webconsole.position"; -const POSITION_ABOVE = "above"; // default const POSITION_WINDOW = "window"; -function tabLoad(aEvent) { - browser.removeEventListener(aEvent.type, arguments.callee, true); +function consoleOpened() { + document.removeEventListener("popupshown", consoleOpened, false); - Services.prefs.setCharPref(POSITION_PREF, POSITION_WINDOW); + let HUD = HUDService.getHudByWindow(content); + ok(HUD.consolePanel, "Web Console opened in a panel"); - openConsole(); + let waitForTitleChange = { + name: "panel title change", + validatorFn: function() { + return HUD.consolePanel.label.indexOf("test2") > -1; + }, + successFn: testEnd, + failureFn: testEnd, + }; - document.addEventListener("popupshown", function popupShown() { - document.removeEventListener("popupshown", popupShown, false); + waitForSuccess({ + name: "initial panel title", + validatorFn: function() { + return HUD.consolePanel.label.indexOf("test1") > -1; + }, + successFn: function() { + content.location = "data:text/html;charset=utf-8,

test2 for bug 663443"; + waitForSuccess(waitForTitleChange); + }, + failureFn: testEnd, + }); +} - let hudId = HUDService.getHudIdByWindow(content); - - ok(hudId, "Web Console is open"); - - let HUD = HUDService.hudReferences[hudId]; - ok(HUD.consolePanel, "Web Console opened in a panel"); - - isnot(HUD.consolePanel.label.indexOf("test1"), -1, "panel title is correct"); - - browser.addEventListener("load", function() { - browser.removeEventListener("load", arguments.callee, true); - - isnot(HUD.consolePanel.label.indexOf("test2"), -1, - "panel title is correct after page navigation"); - - HUD.positionConsole(POSITION_ABOVE); - - closeConsole(); - - executeSoon(finishTest); - }, true); - - content.location = "data:text/html;charset=utf-8,

test2 for bug 663443"; - }, false); +function testEnd() { + closeConsole(null, finishTest); } function test() { addTab(TEST_URI); - browser.addEventListener("load", tabLoad, true); + browser.addEventListener("load", function onLoad() { + browser.removeEventListener("load", onLoad, true); + + Services.prefs.setCharPref(POSITION_PREF, POSITION_WINDOW); + + registerCleanupFunction(function() { + Services.prefs.clearUserPref(POSITION_PREF); + }); + + document.addEventListener("popupshown", consoleOpened, false); + + openConsole(); + }, true); } diff --git a/browser/devtools/webconsole/test/browser_webconsole_bug_678816.js b/browser/devtools/webconsole/test/browser_webconsole_bug_678816.js deleted file mode 100644 index 7681f4c517e..00000000000 --- a/browser/devtools/webconsole/test/browser_webconsole_bug_678816.js +++ /dev/null @@ -1,62 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - http://creativecommons.org/publicdomain/zero/1.0/ */ - -const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/test-console.html"; -const FRAME_SCRIPT_URI ="chrome://mochitests/content/browser/browser/devtools/webconsole/test/test-bug-678816-content.js"; - -let HUD; -let outputItem; - -function tabLoad1(aEvent) { - browser.removeEventListener(aEvent.type, arguments.callee, true); - - openConsole(); - HUD = HUDService.getHudByWindow(content); - - browser.addEventListener("load", tabLoad2, true); - - // Reload so we get some output in the console. - browser.contentWindow.location.reload(); -} - -function tabLoad2(aEvent) { - browser.removeEventListener(aEvent.type, tabLoad2, true); - - outputItem = HUD.outputNode.querySelector(".hud-networkinfo .hud-clickable"); - ok(outputItem, "found a network message"); - document.addEventListener("popupshown", networkPanelShown, false); - - // Click the network message to open the network panel. - EventUtils.synthesizeMouseAtCenter(outputItem, {}); -} - -function networkPanelShown(aEvent) { - document.removeEventListener(aEvent.type, networkPanelShown, false); - - executeSoon(function() { - aEvent.target.addEventListener("popuphidden", networkPanelHidden, false); - aEvent.target.hidePopup(); - }); -} - -function networkPanelHidden(aEvent) { - this.removeEventListener(aEvent.type, networkPanelHidden, false); - - is(HUD.contentWindow, browser.contentWindow, - "console has not been re-attached to the wrong window"); - - finishTest(); -} - -function test() { - messageManager.loadFrameScript(FRAME_SCRIPT_URI, true); - - registerCleanupFunction(function () { - // There's no way to unload a frameScript so send a kill signal to - // unregister the frame script's webProgressListener - messageManager.sendAsyncMessage("bug-678816-kill-webProgressListener"); - }); - - addTab(TEST_URI); - browser.addEventListener("load", tabLoad1, true); -} diff --git a/browser/devtools/webconsole/test/browser_webconsole_consoleonpage.js b/browser/devtools/webconsole/test/browser_webconsole_consoleonpage.js deleted file mode 100644 index c85ae9328b7..00000000000 --- a/browser/devtools/webconsole/test/browser_webconsole_consoleonpage.js +++ /dev/null @@ -1,47 +0,0 @@ -/* vim:set ts=2 sw=2 sts=2 et: */ -/* ***** BEGIN LICENSE BLOCK ***** - * Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ - * - * Contributor(s): - * Julian Viereck - * Mihai Șucan - * - * ***** END LICENSE BLOCK ***** */ - -const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/test-own-console.html"; - -function test() -{ - addTab(TEST_URI); - browser.addEventListener("load", function onLoad() { - browser.removeEventListener("load", onLoad, true); - openConsole(null, testOpenWebConsole); - }, true); -} - -function testOpenWebConsole(aHud) -{ - hud = aHud; - ok(hud, "WebConsole was opened"); - - testOwnConsole(); -} - -function testConsoleOnPage(console) { - isnot(console, undefined, "Console object defined on page"); - is(console.foo, "bar", "Custom console is not overwritten"); -} - -function testOwnConsole() -{ - let console = browser.contentWindow.wrappedJSObject.console; - // Test console on the page. There is already one so it shouldn't be - // overwritten by the WebConsole's console. - testConsoleOnPage(console); - - // Check that the console object is set on the HUD object although there - // is no console object added to the page. - ok(hud.console, "HUD console is defined"); - finishTest(); -} diff --git a/browser/devtools/webconsole/test/browser_webconsole_hud_getters.js b/browser/devtools/webconsole/test/browser_webconsole_hud_getters.js deleted file mode 100644 index a10bdd53b3b..00000000000 --- a/browser/devtools/webconsole/test/browser_webconsole_hud_getters.js +++ /dev/null @@ -1,33 +0,0 @@ -/* vim:set ts=2 sw=2 sts=2 et: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -// Tests that the HUD can be accessed via the HUD references in the HUD -// service. - -const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/test-console.html"; - -function test() { - addTab(TEST_URI); - browser.addEventListener("DOMContentLoaded", testHUDGetters, false); -} - -function testHUDGetters() { - browser.removeEventListener("DOMContentLoaded", testHUDGetters, false); - - openConsole(); - - var HUD = HUDService.getHudByWindow(content); - var jsterm = HUD.jsterm; - var klass = jsterm.inputNode.getAttribute("class"); - ok(klass == "jsterm-input-node", "We have the input node."); - - var hudconsole = HUD.console; - is(typeof hudconsole, "object", "HUD.console is an object"); - is(typeof hudconsole.log, "function", "HUD.console.log is a function"); - is(typeof hudconsole.info, "function", "HUD.console.info is a function"); - - finishTest(); -} - diff --git a/browser/devtools/webconsole/test/browser_webconsole_registries.js b/browser/devtools/webconsole/test/browser_webconsole_registries.js deleted file mode 100644 index 64a4bdfa1ba..00000000000 --- a/browser/devtools/webconsole/test/browser_webconsole_registries.js +++ /dev/null @@ -1,30 +0,0 @@ -/* vim:set ts=2 sw=2 sts=2 et: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -// Tests that the HUD service keeps an accurate registry of all the Web Console -// instances. - -const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/test-console.html"; - -function test() { - addTab(TEST_URI); - browser.addEventListener("DOMContentLoaded", testRegistries, false); -} - -function testRegistries() { - browser.removeEventListener("DOMContentLoaded", testRegistries, false); - - openConsole(); - - let hud = HUDService.getHudByWindow(content); - ok(hud, "we have a HUD"); - ok(HUDService.hudReferences[hud.hudId], "we have a HUD in hudReferences"); - - let windowID = WebConsoleUtils.getOuterWindowId(content); - is(HUDService.windowIds[windowID], hud.hudId, "windowIds are working"); - - finishTest(); -} - diff --git a/browser/devtools/webconsole/test/browser_webconsole_window_zombie.js b/browser/devtools/webconsole/test/browser_webconsole_window_zombie.js index 6f0fa492a36..d4ce62aa41f 100644 --- a/browser/devtools/webconsole/test/browser_webconsole_window_zombie.js +++ b/browser/devtools/webconsole/test/browser_webconsole_window_zombie.js @@ -28,10 +28,10 @@ function consoleOpened(hudRef) { ok(hudRef.consolePanel, "console is in a panel"); - document.addEventListener("popuphidden", function popupHidden() { - document.removeEventListener("popuphidden", popupHidden, false); + Services.obs.addObserver(function onWebConsoleClose() { + Services.obs.removeObserver(onWebConsoleClose, "web-console-destroyed"); executeSoon(finishTest); - }, false); + }, "web-console-destroyed", false); // Close the window console via the menu item let menu = document.getElementById("webConsole"); diff --git a/browser/devtools/webconsole/test/test-bug-678816-content.js b/browser/devtools/webconsole/test/test-bug-678816-content.js deleted file mode 100644 index e4f0d28deec..00000000000 --- a/browser/devtools/webconsole/test/test-bug-678816-content.js +++ /dev/null @@ -1,28 +0,0 @@ -(function () { - let ifaceReq = docShell.QueryInterface(Ci.nsIInterfaceRequestor); - let webProgress = ifaceReq.getInterface(Ci.nsIWebProgress); - - let WebProgressListener = { - onStateChange: function WebProgressListener_onStateChange( - webProgress, request, flag, status) { - - if (flag & Ci.nsIWebProgressListener.STATE_START && - flag & Ci.nsIWebProgressListener.STATE_IS_WINDOW) { - // ensure the dom window is the top one - return (webProgress.DOMWindow.parent == webProgress.DOMWindow); - } - }, - - // ---------- - // Implements progress listener interface. - QueryInterface: XPCOMUtils.generateQI([Ci.nsIWebProgressListener, - Ci.nsISupportsWeakReference]) - }; - - // add web progress listener - webProgress.addProgressListener(WebProgressListener, Ci.nsIWebProgress.NOTIFY_STATE_ALL); - - addMessageListener("bug-678816-kill-webProgressListener", function () { - webProgress.removeProgressListener(WebProgressListener); - }); -})();