michael@0: /* -*- js2-basic-offset: 2; indent-tabs-mode: nil; -*- */ michael@0: /* vim: set ft=javascript ts=2 et sw=2 tw=80: */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: "use strict"; michael@0: michael@0: const {Cc, Ci, Cu} = require("chrome"); michael@0: michael@0: let WebConsoleUtils = require("devtools/toolkit/webconsole/utils").Utils; michael@0: let Heritage = require("sdk/core/heritage"); michael@0: michael@0: loader.lazyGetter(this, "Telemetry", () => require("devtools/shared/telemetry")); michael@0: loader.lazyGetter(this, "WebConsoleFrame", () => require("devtools/webconsole/webconsole").WebConsoleFrame); michael@0: loader.lazyImporter(this, "promise", "resource://gre/modules/Promise.jsm", "Promise"); michael@0: loader.lazyImporter(this, "gDevTools", "resource:///modules/devtools/gDevTools.jsm"); michael@0: loader.lazyImporter(this, "devtools", "resource://gre/modules/devtools/Loader.jsm"); michael@0: loader.lazyImporter(this, "Services", "resource://gre/modules/Services.jsm"); michael@0: loader.lazyImporter(this, "DebuggerServer", "resource://gre/modules/devtools/dbg-server.jsm"); michael@0: loader.lazyImporter(this, "DebuggerClient", "resource://gre/modules/devtools/dbg-client.jsm"); michael@0: michael@0: const STRINGS_URI = "chrome://browser/locale/devtools/webconsole.properties"; michael@0: let l10n = new WebConsoleUtils.l10n(STRINGS_URI); michael@0: michael@0: const BROWSER_CONSOLE_WINDOW_FEATURES = "chrome,titlebar,toolbar,centerscreen,resizable,dialog=no"; michael@0: michael@0: // The preference prefix for all of the Browser Console filters. michael@0: const BROWSER_CONSOLE_FILTER_PREFS_PREFIX = "devtools.browserconsole.filter."; michael@0: michael@0: let gHudId = 0; michael@0: michael@0: /////////////////////////////////////////////////////////////////////////// michael@0: //// The HUD service michael@0: michael@0: function HUD_SERVICE() michael@0: { michael@0: this.consoles = new Map(); michael@0: this.lastFinishedRequest = { callback: null }; michael@0: } michael@0: michael@0: HUD_SERVICE.prototype = michael@0: { michael@0: _browserConsoleID: null, michael@0: _browserConsoleDefer: null, michael@0: michael@0: /** michael@0: * Keeps a reference for each Web Console / Browser Console that is created. michael@0: * @type Map michael@0: */ michael@0: consoles: null, michael@0: michael@0: /** michael@0: * Assign a function to this property to listen for every request that michael@0: * completes. Used by unit tests. The callback takes one argument: the HTTP michael@0: * activity object as received from the remote Web Console. michael@0: * michael@0: * @type object michael@0: * Includes a property named |callback|. Assign the function to the michael@0: * |callback| property of this object. michael@0: */ michael@0: lastFinishedRequest: null, michael@0: michael@0: /** michael@0: * Firefox-specific current tab getter michael@0: * michael@0: * @returns nsIDOMWindow michael@0: */ michael@0: currentContext: function HS_currentContext() { michael@0: return Services.wm.getMostRecentWindow("navigator:browser"); michael@0: }, michael@0: michael@0: /** michael@0: * Open a Web Console for the given target. michael@0: * michael@0: * @see devtools/framework/target.js for details about targets. michael@0: * michael@0: * @param object aTarget michael@0: * The target that the web console will connect to. michael@0: * @param nsIDOMWindow aIframeWindow michael@0: * The window where the web console UI is already loaded. michael@0: * @param nsIDOMWindow aChromeWindow michael@0: * The window of the web console owner. michael@0: * @return object michael@0: * A promise object for the opening of the new WebConsole instance. michael@0: */ michael@0: openWebConsole: michael@0: function HS_openWebConsole(aTarget, aIframeWindow, aChromeWindow) michael@0: { michael@0: let hud = new WebConsole(aTarget, aIframeWindow, aChromeWindow); michael@0: this.consoles.set(hud.hudId, hud); michael@0: return hud.init(); michael@0: }, michael@0: michael@0: /** michael@0: * Open a Browser Console for the given target. michael@0: * michael@0: * @see devtools/framework/target.js for details about targets. michael@0: * michael@0: * @param object aTarget michael@0: * The target that the browser console will connect to. michael@0: * @param nsIDOMWindow aIframeWindow michael@0: * The window where the browser console UI is already loaded. michael@0: * @param nsIDOMWindow aChromeWindow michael@0: * The window of the browser console owner. michael@0: * @return object michael@0: * A promise object for the opening of the new BrowserConsole instance. michael@0: */ michael@0: openBrowserConsole: michael@0: function HS_openBrowserConsole(aTarget, aIframeWindow, aChromeWindow) michael@0: { michael@0: let hud = new BrowserConsole(aTarget, aIframeWindow, aChromeWindow); michael@0: this._browserConsoleID = hud.hudId; michael@0: this.consoles.set(hud.hudId, hud); michael@0: return hud.init(); michael@0: }, michael@0: michael@0: /** michael@0: * Returns the Web Console object associated to a content window. michael@0: * michael@0: * @param nsIDOMWindow aContentWindow michael@0: * @returns object michael@0: */ michael@0: getHudByWindow: function HS_getHudByWindow(aContentWindow) michael@0: { michael@0: for (let [hudId, hud] of this.consoles) { michael@0: let target = hud.target; michael@0: if (target && target.tab && target.window === aContentWindow) { michael@0: return hud; michael@0: } michael@0: } michael@0: return null; michael@0: }, michael@0: michael@0: /** michael@0: * Returns the console instance for a given id. michael@0: * michael@0: * @param string aId michael@0: * @returns Object michael@0: */ michael@0: getHudReferenceById: function HS_getHudReferenceById(aId) michael@0: { michael@0: return this.consoles.get(aId); michael@0: }, michael@0: michael@0: /** michael@0: * Find if there is a Web Console open for the current tab and return the michael@0: * instance. michael@0: * @return object|null michael@0: * The WebConsole object or null if the active tab has no open Web michael@0: * Console. michael@0: */ michael@0: getOpenWebConsole: function HS_getOpenWebConsole() michael@0: { michael@0: let tab = this.currentContext().gBrowser.selectedTab; michael@0: if (!tab || !devtools.TargetFactory.isKnownTab(tab)) { michael@0: return null; michael@0: } michael@0: let target = devtools.TargetFactory.forTab(tab); michael@0: let toolbox = gDevTools.getToolbox(target); michael@0: let panel = toolbox ? toolbox.getPanel("webconsole") : null; michael@0: return panel ? panel.hud : null; michael@0: }, michael@0: michael@0: /** michael@0: * Toggle the Browser Console. michael@0: */ michael@0: toggleBrowserConsole: function HS_toggleBrowserConsole() michael@0: { michael@0: if (this._browserConsoleID) { michael@0: let hud = this.getHudReferenceById(this._browserConsoleID); michael@0: return hud.destroy(); michael@0: } michael@0: michael@0: if (this._browserConsoleDefer) { michael@0: return this._browserConsoleDefer.promise; michael@0: } michael@0: michael@0: this._browserConsoleDefer = promise.defer(); michael@0: michael@0: function connect() michael@0: { michael@0: let deferred = promise.defer(); michael@0: michael@0: if (!DebuggerServer.initialized) { michael@0: DebuggerServer.init(); michael@0: DebuggerServer.addBrowserActors(); michael@0: } michael@0: michael@0: let client = new DebuggerClient(DebuggerServer.connectPipe()); michael@0: client.connect(() => michael@0: client.listTabs((aResponse) => { michael@0: // Add Global Process debugging... michael@0: let globals = JSON.parse(JSON.stringify(aResponse)); michael@0: delete globals.tabs; michael@0: delete globals.selected; michael@0: // ...only if there are appropriate actors (a 'from' property will michael@0: // always be there). michael@0: if (Object.keys(globals).length > 1) { michael@0: deferred.resolve({ form: globals, client: client, chrome: true }); michael@0: } else { michael@0: deferred.reject("Global console not found!"); michael@0: } michael@0: })); michael@0: michael@0: return deferred.promise; michael@0: } michael@0: michael@0: let target; michael@0: function getTarget(aConnection) michael@0: { michael@0: let options = { michael@0: form: aConnection.form, michael@0: client: aConnection.client, michael@0: chrome: true, michael@0: }; michael@0: michael@0: return devtools.TargetFactory.forRemoteTab(options); michael@0: } michael@0: michael@0: function openWindow(aTarget) michael@0: { michael@0: target = aTarget; michael@0: michael@0: let deferred = promise.defer(); michael@0: michael@0: let win = Services.ww.openWindow(null, devtools.Tools.webConsole.url, "_blank", michael@0: BROWSER_CONSOLE_WINDOW_FEATURES, null); michael@0: win.addEventListener("DOMContentLoaded", function onLoad() { michael@0: win.removeEventListener("DOMContentLoaded", onLoad); michael@0: michael@0: // Set the correct Browser Console title. michael@0: let root = win.document.documentElement; michael@0: root.setAttribute("title", root.getAttribute("browserConsoleTitle")); michael@0: michael@0: deferred.resolve(win); michael@0: }); michael@0: michael@0: return deferred.promise; michael@0: } michael@0: michael@0: connect().then(getTarget).then(openWindow).then((aWindow) => { michael@0: this.openBrowserConsole(target, aWindow, aWindow) michael@0: .then((aBrowserConsole) => { michael@0: this._browserConsoleDefer.resolve(aBrowserConsole); michael@0: this._browserConsoleDefer = null; michael@0: }) michael@0: }, console.error); michael@0: michael@0: return this._browserConsoleDefer.promise; michael@0: }, michael@0: michael@0: /** michael@0: * Get the Browser Console instance, if open. michael@0: * michael@0: * @return object|null michael@0: * A BrowserConsole instance or null if the Browser Console is not michael@0: * open. michael@0: */ michael@0: getBrowserConsole: function HS_getBrowserConsole() michael@0: { michael@0: return this.getHudReferenceById(this._browserConsoleID); michael@0: }, michael@0: }; michael@0: michael@0: michael@0: /** michael@0: * A WebConsole instance is an interactive console initialized *per target* michael@0: * that displays console log data as well as provides an interactive terminal to michael@0: * manipulate the target's document content. michael@0: * michael@0: * This object only wraps the iframe that holds the Web Console UI. This is michael@0: * meant to be an integration point between the Firefox UI and the Web Console michael@0: * UI and features. michael@0: * michael@0: * @constructor michael@0: * @param object aTarget michael@0: * The target that the web console will connect to. michael@0: * @param nsIDOMWindow aIframeWindow michael@0: * The window where the web console UI is already loaded. michael@0: * @param nsIDOMWindow aChromeWindow michael@0: * The window of the web console owner. michael@0: */ michael@0: function WebConsole(aTarget, aIframeWindow, aChromeWindow) michael@0: { michael@0: this.iframeWindow = aIframeWindow; michael@0: this.chromeWindow = aChromeWindow; michael@0: this.hudId = "hud_" + ++gHudId; michael@0: this.target = aTarget; michael@0: michael@0: this.browserWindow = this.chromeWindow.top; michael@0: michael@0: let element = this.browserWindow.document.documentElement; michael@0: if (element.getAttribute("windowtype") != "navigator:browser") { michael@0: this.browserWindow = HUDService.currentContext(); michael@0: } michael@0: michael@0: this.ui = new WebConsoleFrame(this); michael@0: } michael@0: michael@0: WebConsole.prototype = { michael@0: iframeWindow: null, michael@0: chromeWindow: null, michael@0: browserWindow: null, michael@0: hudId: null, michael@0: target: null, michael@0: ui: null, michael@0: _browserConsole: false, michael@0: _destroyer: null, michael@0: michael@0: /** michael@0: * Getter for a function to to listen for every request that completes. Used michael@0: * by unit tests. The callback takes one argument: the HTTP activity object as michael@0: * received from the remote Web Console. michael@0: * michael@0: * @type function michael@0: */ michael@0: get lastFinishedRequestCallback() HUDService.lastFinishedRequest.callback, michael@0: michael@0: /** michael@0: * Getter for the window that can provide various utilities that the web michael@0: * console makes use of, like opening links, managing popups, etc. In michael@0: * most cases, this will be |this.browserWindow|, but in some uses (such as michael@0: * the Browser Toolbox), there is no browser window, so an alternative window michael@0: * hosts the utilities there. michael@0: * @type nsIDOMWindow michael@0: */ michael@0: get chromeUtilsWindow() michael@0: { michael@0: if (this.browserWindow) { michael@0: return this.browserWindow; michael@0: } michael@0: return this.chromeWindow.top; michael@0: }, michael@0: michael@0: /** michael@0: * Getter for the xul:popupset that holds any popups we open. michael@0: * @type nsIDOMElement michael@0: */ michael@0: get mainPopupSet() michael@0: { michael@0: return this.chromeUtilsWindow.document.getElementById("mainPopupSet"); michael@0: }, michael@0: michael@0: /** michael@0: * Getter for the output element that holds messages we display. michael@0: * @type nsIDOMElement michael@0: */ michael@0: get outputNode() michael@0: { michael@0: return this.ui ? this.ui.outputNode : null; michael@0: }, michael@0: michael@0: get gViewSourceUtils() michael@0: { michael@0: return this.chromeUtilsWindow.gViewSourceUtils; michael@0: }, michael@0: michael@0: /** michael@0: * Initialize the Web Console instance. michael@0: * michael@0: * @return object michael@0: * A promise for the initialization. michael@0: */ michael@0: init: function WC_init() michael@0: { michael@0: return this.ui.init().then(() => this); michael@0: }, michael@0: michael@0: /** michael@0: * Retrieve the Web Console panel title. michael@0: * michael@0: * @return string michael@0: * The Web Console panel title. michael@0: */ michael@0: getPanelTitle: function WC_getPanelTitle() michael@0: { michael@0: let url = this.ui ? this.ui.contentLocation : ""; michael@0: return l10n.getFormatStr("webConsoleWindowTitleAndURL", [url]); michael@0: }, michael@0: michael@0: /** michael@0: * The JSTerm object that manages the console's input. michael@0: * @see webconsole.js::JSTerm michael@0: * @type object michael@0: */ michael@0: get jsterm() michael@0: { michael@0: return this.ui ? this.ui.jsterm : null; michael@0: }, michael@0: michael@0: /** michael@0: * The clear output button handler. michael@0: * @private michael@0: */ michael@0: _onClearButton: function WC__onClearButton() michael@0: { michael@0: if (this.target.isLocalTab) { michael@0: this.browserWindow.DeveloperToolbar.resetErrorsCount(this.target.tab); michael@0: } michael@0: }, michael@0: michael@0: /** michael@0: * Alias for the WebConsoleFrame.setFilterState() method. michael@0: * @see webconsole.js::WebConsoleFrame.setFilterState() michael@0: */ michael@0: setFilterState: function WC_setFilterState() michael@0: { michael@0: this.ui && this.ui.setFilterState.apply(this.ui, arguments); michael@0: }, michael@0: michael@0: /** michael@0: * Open a link in a new tab. michael@0: * michael@0: * @param string aLink michael@0: * The URL you want to open in a new tab. michael@0: */ michael@0: openLink: function WC_openLink(aLink) michael@0: { michael@0: this.chromeUtilsWindow.openUILinkIn(aLink, "tab"); michael@0: }, michael@0: michael@0: /** michael@0: * Open a link in Firefox's view source. michael@0: * michael@0: * @param string aSourceURL michael@0: * The URL of the file. michael@0: * @param integer aSourceLine michael@0: * The line number which should be highlighted. michael@0: */ michael@0: viewSource: function WC_viewSource(aSourceURL, aSourceLine) michael@0: { michael@0: this.gViewSourceUtils.viewSource(aSourceURL, null, michael@0: this.iframeWindow.document, aSourceLine); michael@0: }, michael@0: michael@0: /** michael@0: * Tries to open a Stylesheet file related to the web page for the web console michael@0: * instance in the Style Editor. If the file is not found, it is opened in michael@0: * source view instead. michael@0: * michael@0: * @param string aSourceURL michael@0: * The URL of the file. michael@0: * @param integer aSourceLine michael@0: * The line number which you want to place the caret. michael@0: * TODO: This function breaks the client-server boundaries. michael@0: * To be fixed in bug 793259. michael@0: */ michael@0: viewSourceInStyleEditor: michael@0: function WC_viewSourceInStyleEditor(aSourceURL, aSourceLine) michael@0: { michael@0: let toolbox = gDevTools.getToolbox(this.target); michael@0: if (!toolbox) { michael@0: this.viewSource(aSourceURL, aSourceLine); michael@0: return; michael@0: } michael@0: michael@0: gDevTools.showToolbox(this.target, "styleeditor").then(function(toolbox) { michael@0: try { michael@0: toolbox.getCurrentPanel().selectStyleSheet(aSourceURL, aSourceLine); michael@0: } catch(e) { michael@0: // Open view source if style editor fails. michael@0: this.viewSource(aSourceURL, aSourceLine); michael@0: } michael@0: }); michael@0: }, michael@0: michael@0: /** michael@0: * Tries to open a JavaScript file related to the web page for the web console michael@0: * instance in the Script Debugger. If the file is not found, it is opened in michael@0: * source view instead. michael@0: * michael@0: * @param string aSourceURL michael@0: * The URL of the file. michael@0: * @param integer aSourceLine michael@0: * The line number which you want to place the caret. michael@0: */ michael@0: viewSourceInDebugger: michael@0: function WC_viewSourceInDebugger(aSourceURL, aSourceLine) michael@0: { michael@0: let toolbox = gDevTools.getToolbox(this.target); michael@0: if (!toolbox) { michael@0: this.viewSource(aSourceURL, aSourceLine); michael@0: return; michael@0: } michael@0: michael@0: let showSource = ({ DebuggerView }) => { michael@0: if (DebuggerView.Sources.containsValue(aSourceURL)) { michael@0: DebuggerView.setEditorLocation(aSourceURL, aSourceLine, michael@0: { noDebug: true }).then(() => { michael@0: this.ui.emit("source-in-debugger-opened"); michael@0: }); michael@0: return; michael@0: } michael@0: toolbox.selectTool("webconsole"); michael@0: this.viewSource(aSourceURL, aSourceLine); michael@0: } michael@0: michael@0: // If the Debugger was already open, switch to it and try to show the michael@0: // source immediately. Otherwise, initialize it and wait for the sources michael@0: // to be added first. michael@0: let debuggerAlreadyOpen = toolbox.getPanel("jsdebugger"); michael@0: toolbox.selectTool("jsdebugger").then(({ panelWin: dbg }) => { michael@0: if (debuggerAlreadyOpen) { michael@0: showSource(dbg); michael@0: } else { michael@0: dbg.once(dbg.EVENTS.SOURCES_ADDED, () => showSource(dbg)); michael@0: } michael@0: }); michael@0: }, michael@0: michael@0: michael@0: /** michael@0: * Tries to open a JavaScript file related to the web page for the web console michael@0: * instance in the corresponding Scratchpad. michael@0: * michael@0: * @param string aSourceURL michael@0: * The URL of the file which corresponds to a Scratchpad id. michael@0: */ michael@0: viewSourceInScratchpad: function WC_viewSourceInScratchpad(aSourceURL) michael@0: { michael@0: // Check for matching top level Scratchpad window. michael@0: let wins = Services.wm.getEnumerator("devtools:scratchpad"); michael@0: michael@0: while (wins.hasMoreElements()) { michael@0: let win = wins.getNext(); michael@0: michael@0: if (!win.closed && win.Scratchpad.uniqueName === aSourceURL) { michael@0: win.focus(); michael@0: return; michael@0: } michael@0: } michael@0: michael@0: // Check for matching Scratchpad toolbox tab. michael@0: for (let [, toolbox] of gDevTools) { michael@0: let scratchpadPanel = toolbox.getPanel("scratchpad"); michael@0: if (scratchpadPanel) { michael@0: let { scratchpad } = scratchpadPanel; michael@0: if (scratchpad.uniqueName === aSourceURL) { michael@0: toolbox.selectTool("scratchpad"); michael@0: toolbox.raise(); michael@0: scratchpad.editor.focus(); michael@0: return; michael@0: } michael@0: } michael@0: } michael@0: }, michael@0: michael@0: /** michael@0: * Retrieve information about the JavaScript debugger's stackframes list. This michael@0: * is used to allow the Web Console to evaluate code in the selected michael@0: * stackframe. michael@0: * michael@0: * @return object|null michael@0: * An object which holds: michael@0: * - frames: the active ThreadClient.cachedFrames array. michael@0: * - selected: depth/index of the selected stackframe in the debugger michael@0: * UI. michael@0: * If the debugger is not open or if it's not paused, then |null| is michael@0: * returned. michael@0: */ michael@0: getDebuggerFrames: function WC_getDebuggerFrames() michael@0: { michael@0: let toolbox = gDevTools.getToolbox(this.target); michael@0: if (!toolbox) { michael@0: return null; michael@0: } michael@0: let panel = toolbox.getPanel("jsdebugger"); michael@0: if (!panel) { michael@0: return null; michael@0: } michael@0: let framesController = panel.panelWin.DebuggerController.StackFrames; michael@0: let thread = framesController.activeThread; michael@0: if (thread && thread.paused) { michael@0: return { michael@0: frames: thread.cachedFrames, michael@0: selected: framesController.currentFrameDepth, michael@0: }; michael@0: } michael@0: return null; michael@0: }, michael@0: michael@0: /** michael@0: * Destroy the object. Call this method to avoid memory leaks when the Web michael@0: * Console is closed. michael@0: * michael@0: * @return object michael@0: * A promise object that is resolved once the Web Console is closed. michael@0: */ michael@0: destroy: function WC_destroy() michael@0: { michael@0: if (this._destroyer) { michael@0: return this._destroyer.promise; michael@0: } michael@0: michael@0: HUDService.consoles.delete(this.hudId); michael@0: michael@0: this._destroyer = promise.defer(); michael@0: michael@0: let popupset = this.mainPopupSet; michael@0: let panels = popupset.querySelectorAll("panel[hudId=" + this.hudId + "]"); michael@0: for (let panel of panels) { michael@0: panel.hidePopup(); michael@0: } michael@0: michael@0: let onDestroy = function WC_onDestroyUI() { michael@0: try { michael@0: let tabWindow = this.target.isLocalTab ? this.target.window : null; michael@0: tabWindow && tabWindow.focus(); michael@0: } michael@0: catch (ex) { michael@0: // Tab focus can fail if the tab or target is closed. michael@0: } michael@0: michael@0: let id = WebConsoleUtils.supportsString(this.hudId); michael@0: Services.obs.notifyObservers(id, "web-console-destroyed", null); michael@0: this._destroyer.resolve(null); michael@0: }.bind(this); michael@0: michael@0: if (this.ui) { michael@0: this.ui.destroy().then(onDestroy); michael@0: } michael@0: else { michael@0: onDestroy(); michael@0: } michael@0: michael@0: return this._destroyer.promise; michael@0: }, michael@0: }; michael@0: michael@0: michael@0: /** michael@0: * A BrowserConsole instance is an interactive console initialized *per target* michael@0: * that displays console log data as well as provides an interactive terminal to michael@0: * manipulate the target's document content. michael@0: * michael@0: * This object only wraps the iframe that holds the Browser Console UI. This is michael@0: * meant to be an integration point between the Firefox UI and the Browser Console michael@0: * UI and features. michael@0: * michael@0: * @constructor michael@0: * @param object aTarget michael@0: * The target that the browser console will connect to. michael@0: * @param nsIDOMWindow aIframeWindow michael@0: * The window where the browser console UI is already loaded. michael@0: * @param nsIDOMWindow aChromeWindow michael@0: * The window of the browser console owner. michael@0: */ michael@0: function BrowserConsole() michael@0: { michael@0: WebConsole.apply(this, arguments); michael@0: this._telemetry = new Telemetry(); michael@0: } michael@0: michael@0: BrowserConsole.prototype = Heritage.extend(WebConsole.prototype, michael@0: { michael@0: _browserConsole: true, michael@0: _bc_init: null, michael@0: _bc_destroyer: null, michael@0: michael@0: $init: WebConsole.prototype.init, michael@0: michael@0: /** michael@0: * Initialize the Browser Console instance. michael@0: * michael@0: * @return object michael@0: * A promise for the initialization. michael@0: */ michael@0: init: function BC_init() michael@0: { michael@0: if (this._bc_init) { michael@0: return this._bc_init; michael@0: } michael@0: michael@0: this.ui._filterPrefsPrefix = BROWSER_CONSOLE_FILTER_PREFS_PREFIX; michael@0: michael@0: let window = this.iframeWindow; michael@0: michael@0: // Make sure that the closing of the Browser Console window destroys this michael@0: // instance. michael@0: let onClose = () => { michael@0: window.removeEventListener("unload", onClose); michael@0: this.destroy(); michael@0: }; michael@0: window.addEventListener("unload", onClose); michael@0: michael@0: // Make sure Ctrl-W closes the Browser Console window. michael@0: window.document.getElementById("cmd_close").removeAttribute("disabled"); michael@0: michael@0: this._telemetry.toolOpened("browserconsole"); michael@0: michael@0: this._bc_init = this.$init(); michael@0: return this._bc_init; michael@0: }, michael@0: michael@0: $destroy: WebConsole.prototype.destroy, michael@0: michael@0: /** michael@0: * Destroy the object. michael@0: * michael@0: * @return object michael@0: * A promise object that is resolved once the Browser Console is closed. michael@0: */ michael@0: destroy: function BC_destroy() michael@0: { michael@0: if (this._bc_destroyer) { michael@0: return this._bc_destroyer.promise; michael@0: } michael@0: michael@0: this._telemetry.toolClosed("browserconsole"); michael@0: michael@0: this._bc_destroyer = promise.defer(); michael@0: michael@0: let chromeWindow = this.chromeWindow; michael@0: this.$destroy().then(() => michael@0: this.target.client.close(() => { michael@0: HUDService._browserConsoleID = null; michael@0: chromeWindow.close(); michael@0: this._bc_destroyer.resolve(null); michael@0: })); michael@0: michael@0: return this._bc_destroyer.promise; michael@0: }, michael@0: }); michael@0: michael@0: const HUDService = new HUD_SERVICE(); michael@0: michael@0: (() => { michael@0: let methods = ["openWebConsole", "openBrowserConsole", michael@0: "toggleBrowserConsole", "getOpenWebConsole", michael@0: "getBrowserConsole", "getHudByWindow", "getHudReferenceById"]; michael@0: for (let method of methods) { michael@0: exports[method] = HUDService[method].bind(HUDService); michael@0: } michael@0: michael@0: exports.consoles = HUDService.consoles; michael@0: exports.lastFinishedRequest = HUDService.lastFinishedRequest; michael@0: })();