2010-06-22 16:51:50 +00:00
|
|
|
/* -*- Mode: js2; js2-basic-offset: 2; indent-tabs-mode: nil; -*- */
|
2010-07-19 13:51:51 +00:00
|
|
|
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
2012-05-21 11:12:37 +00:00
|
|
|
/* 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/. */
|
2010-06-22 16:51:50 +00:00
|
|
|
|
2012-07-26 15:06:04 +00:00
|
|
|
"use strict";
|
|
|
|
|
2010-06-22 16:51:50 +00:00
|
|
|
const Cc = Components.classes;
|
|
|
|
const Ci = Components.interfaces;
|
|
|
|
const Cu = Components.utils;
|
|
|
|
|
|
|
|
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
2013-01-11 17:31:09 +00:00
|
|
|
|
|
|
|
XPCOMUtils.defineLazyModuleGetter(this, "gDevTools",
|
|
|
|
"resource:///modules/devtools/gDevTools.jsm");
|
2012-11-30 08:07:59 +00:00
|
|
|
|
2013-04-11 20:59:08 +00:00
|
|
|
XPCOMUtils.defineLazyModuleGetter(this, "devtools",
|
2013-05-01 16:27:24 +00:00
|
|
|
"resource://gre/modules/devtools/Loader.jsm");
|
2010-12-23 15:59:19 +00:00
|
|
|
|
2012-07-26 15:06:04 +00:00
|
|
|
XPCOMUtils.defineLazyModuleGetter(this, "Services",
|
2013-01-11 17:31:09 +00:00
|
|
|
"resource://gre/modules/Services.jsm");
|
2012-05-29 12:48:05 +00:00
|
|
|
|
2013-04-09 09:47:23 +00:00
|
|
|
XPCOMUtils.defineLazyModuleGetter(this, "DebuggerServer",
|
|
|
|
"resource://gre/modules/devtools/dbg-server.jsm");
|
|
|
|
|
|
|
|
XPCOMUtils.defineLazyModuleGetter(this, "DebuggerClient",
|
|
|
|
"resource://gre/modules/devtools/dbg-client.jsm");
|
|
|
|
|
2012-05-29 12:48:05 +00:00
|
|
|
XPCOMUtils.defineLazyModuleGetter(this, "WebConsoleUtils",
|
2013-01-11 17:31:09 +00:00
|
|
|
"resource://gre/modules/devtools/WebConsoleUtils.jsm");
|
|
|
|
|
|
|
|
XPCOMUtils.defineLazyModuleGetter(this, "Promise",
|
2013-02-01 19:43:15 +00:00
|
|
|
"resource://gre/modules/commonjs/sdk/core/promise.js");
|
2012-01-06 19:34:56 +00:00
|
|
|
|
2013-06-21 14:33:56 +00:00
|
|
|
XPCOMUtils.defineLazyModuleGetter(this, "Heritage",
|
2013-04-09 09:47:23 +00:00
|
|
|
"resource:///modules/devtools/ViewHelpers.jsm");
|
|
|
|
|
2013-05-24 10:26:17 +00:00
|
|
|
let Telemetry = devtools.require("devtools/shared/telemetry");
|
|
|
|
|
2012-09-26 17:07:57 +00:00
|
|
|
const STRINGS_URI = "chrome://browser/locale/devtools/webconsole.properties";
|
|
|
|
let l10n = new WebConsoleUtils.l10n(STRINGS_URI);
|
2012-07-26 15:06:04 +00:00
|
|
|
|
2013-04-09 09:47:23 +00:00
|
|
|
const BROWSER_CONSOLE_WINDOW_FEATURES = "chrome,titlebar,toolbar,centerscreen,resizable,dialog=no";
|
|
|
|
|
2013-06-20 13:29:01 +00:00
|
|
|
// The preference prefix for all of the Browser Console filters.
|
|
|
|
const BROWSER_CONSOLE_FILTER_PREFS_PREFIX = "devtools.browserconsole.filter.";
|
|
|
|
|
2012-10-31 16:13:28 +00:00
|
|
|
this.EXPORTED_SYMBOLS = ["HUDService"];
|
2012-07-26 15:06:04 +00:00
|
|
|
|
2010-09-09 00:08:58 +00:00
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
|
|
//// The HUD service
|
|
|
|
|
2010-06-22 16:51:50 +00:00
|
|
|
function HUD_SERVICE()
|
|
|
|
{
|
2013-01-11 17:31:09 +00:00
|
|
|
this.hudReferences = {};
|
|
|
|
}
|
2010-11-20 19:53:14 +00:00
|
|
|
|
2013-01-11 17:31:09 +00:00
|
|
|
HUD_SERVICE.prototype =
|
|
|
|
{
|
2011-08-03 18:04:30 +00:00
|
|
|
/**
|
|
|
|
* Keeps a reference for each HeadsUpDisplay that is created
|
2013-01-11 17:31:09 +00:00
|
|
|
* @type object
|
2011-08-03 18:04:30 +00:00
|
|
|
*/
|
2013-01-11 17:31:09 +00:00
|
|
|
hudReferences: null,
|
2010-06-22 16:51:50 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* getter for UI commands to be used by the frontend
|
|
|
|
*
|
|
|
|
* @returns object
|
|
|
|
*/
|
|
|
|
get consoleUI() {
|
|
|
|
return HeadsUpDisplayUICommands;
|
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Firefox-specific current tab getter
|
|
|
|
*
|
|
|
|
* @returns nsIDOMWindow
|
|
|
|
*/
|
|
|
|
currentContext: function HS_currentContext() {
|
2012-05-31 10:30:56 +00:00
|
|
|
return Services.wm.getMostRecentWindow("navigator:browser");
|
2010-06-22 16:51:50 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
2013-01-11 17:31:09 +00:00
|
|
|
* Open a Web Console for the given target.
|
|
|
|
*
|
2013-04-11 20:59:08 +00:00
|
|
|
* @see devtools/framework/target.js for details about targets.
|
2010-06-22 16:51:50 +00:00
|
|
|
*
|
2013-01-11 17:31:09 +00:00
|
|
|
* @param object aTarget
|
|
|
|
* The target that the web console will connect to.
|
2013-04-09 09:47:23 +00:00
|
|
|
* @param nsIDOMWindow aIframeWindow
|
|
|
|
* The window where the web console UI is already loaded.
|
|
|
|
* @param nsIDOMWindow aChromeWindow
|
|
|
|
* The window of the web console owner.
|
2012-05-31 10:30:56 +00:00
|
|
|
* @return object
|
2013-01-11 17:31:09 +00:00
|
|
|
* A Promise object for the opening of the new WebConsole instance.
|
2010-06-22 16:51:50 +00:00
|
|
|
*/
|
2013-04-09 09:47:23 +00:00
|
|
|
openWebConsole:
|
|
|
|
function HS_openWebConsole(aTarget, aIframeWindow, aChromeWindow)
|
|
|
|
{
|
|
|
|
let hud = new WebConsole(aTarget, aIframeWindow, aChromeWindow);
|
|
|
|
this.hudReferences[hud.hudId] = hud;
|
|
|
|
return hud.init();
|
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Open a Browser Console for the given target.
|
|
|
|
*
|
|
|
|
* @see devtools/framework/Target.jsm for details about targets.
|
|
|
|
*
|
|
|
|
* @param object aTarget
|
|
|
|
* The target that the browser console will connect to.
|
|
|
|
* @param nsIDOMWindow aIframeWindow
|
|
|
|
* The window where the browser console UI is already loaded.
|
|
|
|
* @param nsIDOMWindow aChromeWindow
|
|
|
|
* The window of the browser console owner.
|
|
|
|
* @return object
|
|
|
|
* A Promise object for the opening of the new BrowserConsole instance.
|
|
|
|
*/
|
|
|
|
openBrowserConsole:
|
|
|
|
function HS_openBrowserConsole(aTarget, aIframeWindow, aChromeWindow)
|
2010-06-22 16:51:50 +00:00
|
|
|
{
|
2013-04-09 09:47:23 +00:00
|
|
|
let hud = new BrowserConsole(aTarget, aIframeWindow, aChromeWindow);
|
2013-01-11 17:31:09 +00:00
|
|
|
this.hudReferences[hud.hudId] = hud;
|
|
|
|
return hud.init();
|
2010-06-22 16:51:50 +00:00
|
|
|
},
|
|
|
|
|
2010-08-26 16:49:28 +00:00
|
|
|
/**
|
2011-07-01 20:20:09 +00:00
|
|
|
* Returns the HeadsUpDisplay object associated to a content window.
|
2010-08-26 16:49:28 +00:00
|
|
|
*
|
|
|
|
* @param nsIDOMWindow aContentWindow
|
2011-07-01 20:20:09 +00:00
|
|
|
* @returns object
|
2010-08-26 16:49:28 +00:00
|
|
|
*/
|
2011-07-01 20:20:09 +00:00
|
|
|
getHudByWindow: function HS_getHudByWindow(aContentWindow)
|
2010-08-26 16:49:28 +00:00
|
|
|
{
|
2013-01-11 17:31:09 +00:00
|
|
|
for each (let hud in this.hudReferences) {
|
|
|
|
let target = hud.target;
|
|
|
|
if (target && target.tab && target.window === aContentWindow) {
|
|
|
|
return hud;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return null;
|
2010-08-26 16:49:28 +00:00
|
|
|
},
|
|
|
|
|
2011-02-25 22:12:42 +00:00
|
|
|
/**
|
2011-07-01 20:20:09 +00:00
|
|
|
* Returns the hudId that is corresponding to the hud activated for the
|
|
|
|
* passed aContentWindow. If there is no matching hudId null is returned.
|
2011-02-25 22:12:42 +00:00
|
|
|
*
|
2011-07-01 20:20:09 +00:00
|
|
|
* @param nsIDOMWindow aContentWindow
|
|
|
|
* @returns string or null
|
2011-02-25 22:12:42 +00:00
|
|
|
*/
|
2011-07-01 20:20:09 +00:00
|
|
|
getHudIdByWindow: function HS_getHudIdByWindow(aContentWindow)
|
2011-02-25 22:12:42 +00:00
|
|
|
{
|
2013-01-11 17:31:09 +00:00
|
|
|
let hud = this.getHudByWindow(aContentWindow);
|
|
|
|
return hud ? hud.hudId : null;
|
2011-02-25 22:12:42 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns the hudReference for a given id.
|
|
|
|
*
|
|
|
|
* @param string aId
|
|
|
|
* @returns Object
|
|
|
|
*/
|
|
|
|
getHudReferenceById: function HS_getHudReferenceById(aId)
|
|
|
|
{
|
|
|
|
return aId in this.hudReferences ? this.hudReferences[aId] : null;
|
|
|
|
},
|
|
|
|
|
2010-08-29 04:30:49 +00:00
|
|
|
/**
|
2012-05-29 12:48:05 +00:00
|
|
|
* Assign a function to this property to listen for every request that
|
|
|
|
* completes. Used by unit tests. The callback takes one argument: the HTTP
|
|
|
|
* activity object as received from the remote Web Console.
|
|
|
|
*
|
|
|
|
* @type function
|
2010-08-29 04:30:49 +00:00
|
|
|
*/
|
|
|
|
lastFinishedRequestCallback: null,
|
2010-06-22 16:51:50 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2012-05-31 10:30:56 +00:00
|
|
|
/**
|
2013-01-11 17:31:09 +00:00
|
|
|
* A WebConsole instance is an interactive console initialized *per target*
|
2012-07-26 15:06:04 +00:00
|
|
|
* that displays console log data as well as provides an interactive terminal to
|
2013-01-11 17:31:09 +00:00
|
|
|
* manipulate the target's document content.
|
2012-05-31 10:30:56 +00:00
|
|
|
*
|
2013-04-09 09:47:23 +00:00
|
|
|
* This object only wraps the iframe that holds the Web Console UI. This is
|
|
|
|
* meant to be an integration point between the Firefox UI and the Web Console
|
|
|
|
* UI and features.
|
2012-07-26 15:06:04 +00:00
|
|
|
*
|
2013-01-11 17:31:09 +00:00
|
|
|
* @constructor
|
|
|
|
* @param object aTarget
|
|
|
|
* The target that the web console will connect to.
|
2013-04-09 09:47:23 +00:00
|
|
|
* @param nsIDOMWindow aIframeWindow
|
|
|
|
* The window where the web console UI is already loaded.
|
|
|
|
* @param nsIDOMWindow aChromeWindow
|
|
|
|
* The window of the web console owner.
|
2012-05-31 10:30:56 +00:00
|
|
|
*/
|
2013-04-09 09:47:23 +00:00
|
|
|
function WebConsole(aTarget, aIframeWindow, aChromeWindow)
|
2010-06-22 16:51:50 +00:00
|
|
|
{
|
2013-04-09 09:47:23 +00:00
|
|
|
this.iframeWindow = aIframeWindow;
|
|
|
|
this.chromeWindow = aChromeWindow;
|
2013-01-11 17:31:09 +00:00
|
|
|
this.hudId = "hud_" + Date.now();
|
2012-11-30 08:07:59 +00:00
|
|
|
this.target = aTarget;
|
2013-02-17 11:13:00 +00:00
|
|
|
|
|
|
|
this.browserWindow = this.chromeWindow.top;
|
2013-04-09 09:47:23 +00:00
|
|
|
|
2013-02-17 11:13:00 +00:00
|
|
|
let element = this.browserWindow.document.documentElement;
|
|
|
|
if (element.getAttribute("windowtype") != "navigator:browser") {
|
|
|
|
this.browserWindow = HUDService.currentContext();
|
|
|
|
}
|
2013-06-20 13:29:01 +00:00
|
|
|
|
|
|
|
this.ui = new this.iframeWindow.WebConsoleFrame(this);
|
2010-06-22 16:51:50 +00:00
|
|
|
}
|
|
|
|
|
2012-07-26 15:06:04 +00:00
|
|
|
WebConsole.prototype = {
|
2013-04-09 09:47:23 +00:00
|
|
|
iframeWindow: null,
|
2012-10-05 16:15:51 +00:00
|
|
|
chromeWindow: null,
|
2013-04-09 09:47:23 +00:00
|
|
|
browserWindow: null,
|
2013-01-11 17:31:09 +00:00
|
|
|
hudId: null,
|
|
|
|
target: null,
|
2013-06-20 13:29:01 +00:00
|
|
|
ui: null,
|
2013-04-09 09:47:23 +00:00
|
|
|
_browserConsole: false,
|
2013-01-11 17:31:09 +00:00
|
|
|
_destroyer: null,
|
|
|
|
|
2012-06-02 10:45:32 +00:00
|
|
|
/**
|
2012-07-26 15:06:04 +00:00
|
|
|
* Getter for HUDService.lastFinishedRequestCallback.
|
2012-06-02 10:45:32 +00:00
|
|
|
*
|
2012-07-26 15:06:04 +00:00
|
|
|
* @see HUDService.lastFinishedRequestCallback
|
|
|
|
* @type function
|
2012-06-02 10:45:32 +00:00
|
|
|
*/
|
2012-07-26 15:06:04 +00:00
|
|
|
get lastFinishedRequestCallback() HUDService.lastFinishedRequestCallback,
|
2012-06-02 10:45:32 +00:00
|
|
|
|
2012-05-29 12:48:05 +00:00
|
|
|
/**
|
2012-07-26 15:06:04 +00:00
|
|
|
* Getter for the xul:popupset that holds any popups we open.
|
|
|
|
* @type nsIDOMElement
|
2012-05-29 12:48:05 +00:00
|
|
|
*/
|
2012-07-26 15:06:04 +00:00
|
|
|
get mainPopupSet()
|
|
|
|
{
|
2013-01-11 17:31:09 +00:00
|
|
|
return this.browserWindow.document.getElementById("mainPopupSet");
|
2012-07-26 15:06:04 +00:00
|
|
|
},
|
2012-05-29 12:48:05 +00:00
|
|
|
|
2012-07-26 15:06:04 +00:00
|
|
|
/**
|
|
|
|
* Getter for the output element that holds messages we display.
|
|
|
|
* @type nsIDOMElement
|
|
|
|
*/
|
|
|
|
get outputNode()
|
|
|
|
{
|
|
|
|
return this.ui ? this.ui.outputNode : null;
|
|
|
|
},
|
|
|
|
|
2013-01-11 17:31:09 +00:00
|
|
|
get gViewSourceUtils() this.browserWindow.gViewSourceUtils,
|
2012-07-26 15:06:04 +00:00
|
|
|
|
|
|
|
/**
|
2013-01-11 17:31:09 +00:00
|
|
|
* Initialize the Web Console instance.
|
|
|
|
*
|
|
|
|
* @return object
|
|
|
|
* A Promise for the initialization.
|
2012-07-26 15:06:04 +00:00
|
|
|
*/
|
2013-01-11 17:31:09 +00:00
|
|
|
init: function WC_init()
|
2012-07-26 15:06:04 +00:00
|
|
|
{
|
2013-04-09 09:47:23 +00:00
|
|
|
return this.ui.init().then(() => this);
|
2011-05-18 11:08:54 +00:00
|
|
|
},
|
|
|
|
|
2011-06-18 14:42:14 +00:00
|
|
|
/**
|
|
|
|
* Retrieve the Web Console panel title.
|
|
|
|
*
|
|
|
|
* @return string
|
|
|
|
* The Web Console panel title.
|
|
|
|
*/
|
2012-07-26 15:06:04 +00:00
|
|
|
getPanelTitle: function WC_getPanelTitle()
|
2011-06-18 14:42:14 +00:00
|
|
|
{
|
2012-10-05 11:54:43 +00:00
|
|
|
let url = this.ui ? this.ui.contentLocation : "";
|
|
|
|
return l10n.getFormatStr("webConsoleWindowTitleAndURL", [url]);
|
2011-06-18 14:42:14 +00:00
|
|
|
},
|
|
|
|
|
2010-06-22 16:51:50 +00:00
|
|
|
/**
|
2012-07-26 15:06:04 +00:00
|
|
|
* The JSTerm object that manages the console's input.
|
|
|
|
* @see webconsole.js::JSTerm
|
|
|
|
* @type object
|
2010-06-22 16:51:50 +00:00
|
|
|
*/
|
2012-07-26 15:06:04 +00:00
|
|
|
get jsterm()
|
2010-06-22 16:51:50 +00:00
|
|
|
{
|
2012-07-26 15:06:04 +00:00
|
|
|
return this.ui ? this.ui.jsterm : null;
|
2010-06-22 16:51:50 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
2012-07-26 15:06:04 +00:00
|
|
|
* The clear output button handler.
|
2012-09-26 17:02:04 +00:00
|
|
|
* @private
|
2010-06-22 16:51:50 +00:00
|
|
|
*/
|
2012-09-26 17:02:04 +00:00
|
|
|
_onClearButton: function WC__onClearButton()
|
2010-06-22 16:51:50 +00:00
|
|
|
{
|
2013-01-11 17:31:09 +00:00
|
|
|
if (this.target.isLocalTab) {
|
|
|
|
this.browserWindow.DeveloperToolbar.resetErrorsCount(this.target.tab);
|
|
|
|
}
|
2010-06-22 16:51:50 +00:00
|
|
|
},
|
|
|
|
|
2011-06-09 13:27:30 +00:00
|
|
|
/**
|
2012-07-26 15:06:04 +00:00
|
|
|
* Alias for the WebConsoleFrame.setFilterState() method.
|
|
|
|
* @see webconsole.js::WebConsoleFrame.setFilterState()
|
2011-06-09 13:27:30 +00:00
|
|
|
*/
|
2012-07-26 15:06:04 +00:00
|
|
|
setFilterState: function WC_setFilterState()
|
2011-06-09 13:27:30 +00:00
|
|
|
{
|
2012-07-26 15:06:04 +00:00
|
|
|
this.ui && this.ui.setFilterState.apply(this.ui, arguments);
|
2011-06-09 13:27:30 +00:00
|
|
|
},
|
|
|
|
|
2011-05-18 11:08:54 +00:00
|
|
|
/**
|
2012-07-26 15:06:04 +00:00
|
|
|
* Open a link in a new tab.
|
2011-05-18 11:08:54 +00:00
|
|
|
*
|
2012-07-26 15:06:04 +00:00
|
|
|
* @param string aLink
|
|
|
|
* The URL you want to open in a new tab.
|
2011-05-18 11:08:54 +00:00
|
|
|
*/
|
2012-07-26 15:06:04 +00:00
|
|
|
openLink: function WC_openLink(aLink)
|
2010-06-22 16:51:50 +00:00
|
|
|
{
|
2013-01-11 17:31:09 +00:00
|
|
|
this.browserWindow.openUILinkIn(aLink, "tab");
|
2010-06-22 16:51:50 +00:00
|
|
|
},
|
|
|
|
|
2012-09-25 17:32:11 +00:00
|
|
|
/**
|
|
|
|
* Open a link in Firefox's view source.
|
|
|
|
*
|
|
|
|
* @param string aSourceURL
|
|
|
|
* The URL of the file.
|
|
|
|
* @param integer aSourceLine
|
|
|
|
* The line number which should be highlighted.
|
|
|
|
*/
|
|
|
|
viewSource: function WC_viewSource(aSourceURL, aSourceLine)
|
|
|
|
{
|
|
|
|
this.gViewSourceUtils.viewSource(aSourceURL, null,
|
|
|
|
this.iframeWindow.document, aSourceLine);
|
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Tries to open a Stylesheet file related to the web page for the web console
|
|
|
|
* instance in the Style Editor. If the file is not found, it is opened in
|
|
|
|
* source view instead.
|
|
|
|
*
|
|
|
|
* @param string aSourceURL
|
|
|
|
* The URL of the file.
|
|
|
|
* @param integer aSourceLine
|
|
|
|
* The line number which you want to place the caret.
|
|
|
|
* TODO: This function breaks the client-server boundaries.
|
|
|
|
* To be fixed in bug 793259.
|
|
|
|
*/
|
|
|
|
viewSourceInStyleEditor:
|
|
|
|
function WC_viewSourceInStyleEditor(aSourceURL, aSourceLine)
|
|
|
|
{
|
2013-05-30 20:23:52 +00:00
|
|
|
let toolbox = gDevTools.getToolbox(this.target);
|
|
|
|
if (!toolbox) {
|
|
|
|
this.viewSource(aSourceURL, aSourceLine);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2013-04-25 16:46:13 +00:00
|
|
|
gDevTools.showToolbox(this.target, "styleeditor").then(function(toolbox) {
|
|
|
|
try {
|
|
|
|
toolbox.getCurrentPanel().selectStyleSheet(aSourceURL, aSourceLine);
|
|
|
|
} catch(e) {
|
|
|
|
// Open view source if style editor fails.
|
|
|
|
this.viewSource(aSourceURL, aSourceLine);
|
2012-09-25 17:32:11 +00:00
|
|
|
}
|
2013-04-25 16:46:13 +00:00
|
|
|
});
|
2012-09-25 17:32:11 +00:00
|
|
|
},
|
|
|
|
|
2012-12-16 23:10:44 +00:00
|
|
|
/**
|
|
|
|
* Tries to open a JavaScript file related to the web page for the web console
|
|
|
|
* instance in the Script Debugger. If the file is not found, it is opened in
|
|
|
|
* source view instead.
|
|
|
|
*
|
|
|
|
* @param string aSourceURL
|
|
|
|
* The URL of the file.
|
|
|
|
* @param integer aSourceLine
|
|
|
|
* The line number which you want to place the caret.
|
|
|
|
*/
|
|
|
|
viewSourceInDebugger:
|
|
|
|
function WC_viewSourceInDebugger(aSourceURL, aSourceLine)
|
|
|
|
{
|
|
|
|
let self = this;
|
|
|
|
let panelWin = null;
|
|
|
|
let debuggerWasOpen = true;
|
|
|
|
let toolbox = gDevTools.getToolbox(this.target);
|
2013-04-09 09:47:23 +00:00
|
|
|
if (!toolbox) {
|
|
|
|
self.viewSource(aSourceURL, aSourceLine);
|
|
|
|
return;
|
|
|
|
}
|
2012-12-16 23:10:44 +00:00
|
|
|
|
|
|
|
if (!toolbox.getPanel("jsdebugger")) {
|
|
|
|
debuggerWasOpen = false;
|
|
|
|
let toolboxWin = toolbox.doc.defaultView;
|
|
|
|
toolboxWin.addEventListener("Debugger:AfterSourcesAdded",
|
|
|
|
function afterSourcesAdded() {
|
|
|
|
toolboxWin.removeEventListener("Debugger:AfterSourcesAdded",
|
|
|
|
afterSourcesAdded);
|
|
|
|
loadScript();
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
toolbox.selectTool("jsdebugger").then(function onDebuggerOpen(dbg) {
|
|
|
|
panelWin = dbg.panelWin;
|
|
|
|
if (debuggerWasOpen) {
|
|
|
|
loadScript();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
function loadScript() {
|
|
|
|
let debuggerView = panelWin.DebuggerView;
|
|
|
|
if (!debuggerView.Sources.containsValue(aSourceURL)) {
|
|
|
|
toolbox.selectTool("webconsole");
|
|
|
|
self.viewSource(aSourceURL, aSourceLine);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (debuggerWasOpen && debuggerView.Sources.selectedValue == aSourceURL) {
|
|
|
|
debuggerView.editor.setCaretPosition(aSourceLine - 1);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
panelWin.addEventListener("Debugger:SourceShown", onSource, false);
|
|
|
|
debuggerView.Sources.preferredSource = aSourceURL;
|
|
|
|
}
|
|
|
|
|
|
|
|
function onSource(aEvent) {
|
|
|
|
if (aEvent.detail.url != aSourceURL) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
panelWin.removeEventListener("Debugger:SourceShown", onSource, false);
|
|
|
|
panelWin.DebuggerView.editor.setCaretPosition(aSourceLine - 1);
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
2013-03-30 11:31:10 +00:00
|
|
|
/**
|
|
|
|
* Retrieve information about the JavaScript debugger's stackframes list. This
|
|
|
|
* is used to allow the Web Console to evaluate code in the selected
|
|
|
|
* stackframe.
|
|
|
|
*
|
|
|
|
* @return object|null
|
|
|
|
* An object which holds:
|
|
|
|
* - frames: the active ThreadClient.cachedFrames array.
|
|
|
|
* - selected: depth/index of the selected stackframe in the debugger
|
|
|
|
* UI.
|
|
|
|
* If the debugger is not open or if it's not paused, then |null| is
|
|
|
|
* returned.
|
|
|
|
*/
|
|
|
|
getDebuggerFrames: function WC_getDebuggerFrames()
|
|
|
|
{
|
|
|
|
let toolbox = gDevTools.getToolbox(this.target);
|
|
|
|
if (!toolbox) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
let panel = toolbox.getPanel("jsdebugger");
|
|
|
|
if (!panel) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
let framesController = panel.panelWin.gStackFrames;
|
|
|
|
let thread = framesController.activeThread;
|
|
|
|
if (thread && thread.paused) {
|
|
|
|
return {
|
|
|
|
frames: thread.cachedFrames,
|
|
|
|
selected: framesController.currentFrame,
|
|
|
|
};
|
|
|
|
}
|
|
|
|
return null;
|
|
|
|
},
|
|
|
|
|
2012-05-10 13:15:10 +00:00
|
|
|
/**
|
2012-07-26 15:06:04 +00:00
|
|
|
* Destroy the object. Call this method to avoid memory leaks when the Web
|
|
|
|
* Console is closed.
|
2012-09-26 17:07:57 +00:00
|
|
|
*
|
2013-01-11 17:31:09 +00:00
|
|
|
* @return object
|
|
|
|
* A Promise object that is resolved once the Web Console is closed.
|
2012-05-10 13:15:10 +00:00
|
|
|
*/
|
2013-01-11 17:31:09 +00:00
|
|
|
destroy: function WC_destroy()
|
2010-06-22 16:51:50 +00:00
|
|
|
{
|
2013-01-11 17:31:09 +00:00
|
|
|
if (this._destroyer) {
|
|
|
|
return this._destroyer.promise;
|
|
|
|
}
|
|
|
|
|
|
|
|
delete HUDService.hudReferences[this.hudId];
|
|
|
|
|
|
|
|
this._destroyer = Promise.defer();
|
2012-05-10 13:15:10 +00:00
|
|
|
|
2012-07-26 15:06:04 +00:00
|
|
|
let popupset = this.mainPopupSet;
|
|
|
|
let panels = popupset.querySelectorAll("panel[hudId=" + this.hudId + "]");
|
|
|
|
for (let panel of panels) {
|
2012-11-30 08:07:59 +00:00
|
|
|
panel.hidePopup();
|
2012-07-26 15:06:04 +00:00
|
|
|
}
|
2012-05-10 13:15:10 +00:00
|
|
|
|
2012-09-26 17:07:57 +00:00
|
|
|
let onDestroy = function WC_onDestroyUI() {
|
2013-01-11 17:31:09 +00:00
|
|
|
try {
|
2013-03-07 07:30:03 +00:00
|
|
|
let tabWindow = this.target.isLocalTab ? this.target.window : null;
|
2013-01-11 17:31:09 +00:00
|
|
|
tabWindow && tabWindow.focus();
|
2012-09-26 17:07:57 +00:00
|
|
|
}
|
2013-01-11 17:31:09 +00:00
|
|
|
catch (ex) {
|
2013-03-07 07:30:03 +00:00
|
|
|
// Tab focus can fail if the tab or target is closed.
|
2012-09-26 17:07:57 +00:00
|
|
|
}
|
2012-05-10 13:15:10 +00:00
|
|
|
|
2013-01-11 17:31:09 +00:00
|
|
|
let id = WebConsoleUtils.supportsString(this.hudId);
|
|
|
|
Services.obs.notifyObservers(id, "web-console-destroyed", null);
|
|
|
|
this._destroyer.resolve(null);
|
2012-09-26 17:07:57 +00:00
|
|
|
}.bind(this);
|
|
|
|
|
|
|
|
if (this.ui) {
|
2013-01-11 17:31:09 +00:00
|
|
|
this.ui.destroy().then(onDestroy);
|
2012-09-26 17:07:57 +00:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
onDestroy();
|
2012-05-10 13:15:10 +00:00
|
|
|
}
|
2013-01-11 17:31:09 +00:00
|
|
|
|
|
|
|
return this._destroyer.promise;
|
2012-07-26 15:06:04 +00:00
|
|
|
},
|
|
|
|
};
|
2012-05-10 13:15:10 +00:00
|
|
|
|
2013-04-09 09:47:23 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* A BrowserConsole instance is an interactive console initialized *per target*
|
|
|
|
* that displays console log data as well as provides an interactive terminal to
|
|
|
|
* manipulate the target's document content.
|
|
|
|
*
|
|
|
|
* This object only wraps the iframe that holds the Browser Console UI. This is
|
|
|
|
* meant to be an integration point between the Firefox UI and the Browser Console
|
|
|
|
* UI and features.
|
|
|
|
*
|
|
|
|
* @constructor
|
|
|
|
* @param object aTarget
|
|
|
|
* The target that the browser console will connect to.
|
|
|
|
* @param nsIDOMWindow aIframeWindow
|
|
|
|
* The window where the browser console UI is already loaded.
|
|
|
|
* @param nsIDOMWindow aChromeWindow
|
|
|
|
* The window of the browser console owner.
|
|
|
|
*/
|
|
|
|
function BrowserConsole()
|
|
|
|
{
|
|
|
|
WebConsole.apply(this, arguments);
|
2013-05-24 10:26:17 +00:00
|
|
|
this._telemetry = new Telemetry();
|
2013-04-09 09:47:23 +00:00
|
|
|
}
|
|
|
|
|
2013-06-21 14:33:56 +00:00
|
|
|
BrowserConsole.prototype = Heritage.extend(WebConsole.prototype,
|
2013-04-09 09:47:23 +00:00
|
|
|
{
|
|
|
|
_browserConsole: true,
|
|
|
|
_bc_init: null,
|
|
|
|
_bc_destroyer: null,
|
|
|
|
|
|
|
|
$init: WebConsole.prototype.init,
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Initialize the Browser Console instance.
|
|
|
|
*
|
|
|
|
* @return object
|
|
|
|
* A Promise for the initialization.
|
|
|
|
*/
|
|
|
|
init: function BC_init()
|
|
|
|
{
|
|
|
|
if (this._bc_init) {
|
|
|
|
return this._bc_init;
|
|
|
|
}
|
|
|
|
|
2013-06-20 13:29:01 +00:00
|
|
|
this.ui._filterPrefsPrefix = BROWSER_CONSOLE_FILTER_PREFS_PREFIX;
|
|
|
|
|
2013-04-09 09:47:23 +00:00
|
|
|
let window = this.iframeWindow;
|
2013-05-30 15:08:14 +00:00
|
|
|
|
|
|
|
// Make sure that the closing of the Browser Console window destroys this
|
|
|
|
// instance.
|
2013-04-09 09:47:23 +00:00
|
|
|
let onClose = () => {
|
|
|
|
window.removeEventListener("unload", onClose);
|
|
|
|
this.destroy();
|
|
|
|
};
|
|
|
|
window.addEventListener("unload", onClose);
|
|
|
|
|
2013-05-30 15:08:14 +00:00
|
|
|
// Make sure Ctrl-W closes the Browser Console window.
|
|
|
|
window.document.getElementById("cmd_close").removeAttribute("disabled");
|
2013-05-16 12:35:53 +00:00
|
|
|
|
2013-05-30 15:08:14 +00:00
|
|
|
this._telemetry.toolOpened("browserconsole");
|
2013-04-09 09:47:23 +00:00
|
|
|
|
2013-05-30 15:08:14 +00:00
|
|
|
this._bc_init = this.$init();
|
2013-04-09 09:47:23 +00:00
|
|
|
return this._bc_init;
|
|
|
|
},
|
|
|
|
|
|
|
|
$destroy: WebConsole.prototype.destroy,
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Destroy the object.
|
|
|
|
*
|
|
|
|
* @return object
|
|
|
|
* A Promise object that is resolved once the Browser Console is closed.
|
|
|
|
*/
|
|
|
|
destroy: function BC_destroy()
|
|
|
|
{
|
|
|
|
if (this._bc_destroyer) {
|
|
|
|
return this._bc_destroyer.promise;
|
|
|
|
}
|
|
|
|
|
2013-05-24 10:26:17 +00:00
|
|
|
this._telemetry.toolClosed("browserconsole");
|
|
|
|
|
2013-04-09 09:47:23 +00:00
|
|
|
this._bc_destroyer = Promise.defer();
|
|
|
|
|
|
|
|
let chromeWindow = this.chromeWindow;
|
|
|
|
this.$destroy().then(() =>
|
|
|
|
this.target.client.close(() => {
|
|
|
|
HeadsUpDisplayUICommands._browserConsoleID = null;
|
|
|
|
chromeWindow.close();
|
|
|
|
this._bc_destroyer.resolve(null);
|
|
|
|
}));
|
|
|
|
|
|
|
|
return this._bc_destroyer.promise;
|
|
|
|
},
|
|
|
|
});
|
|
|
|
|
|
|
|
|
2012-07-26 15:06:04 +00:00
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
// HeadsUpDisplayUICommands
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
2012-06-12 11:25:07 +00:00
|
|
|
|
2012-07-26 15:06:04 +00:00
|
|
|
var HeadsUpDisplayUICommands = {
|
2013-04-09 09:47:23 +00:00
|
|
|
_browserConsoleID: null,
|
|
|
|
_browserConsoleDefer: null,
|
|
|
|
|
2013-01-11 17:31:09 +00:00
|
|
|
/**
|
|
|
|
* Toggle the Web Console for the current tab.
|
|
|
|
*
|
|
|
|
* @return object
|
|
|
|
* A Promise for either the opening of the toolbox that holds the Web
|
|
|
|
* Console, or a Promise for the closing of the toolbox.
|
|
|
|
*/
|
|
|
|
toggleHUD: function UIC_toggleHUD()
|
2012-10-11 18:24:57 +00:00
|
|
|
{
|
2013-01-11 17:31:09 +00:00
|
|
|
let window = HUDService.currentContext();
|
2013-04-11 20:59:08 +00:00
|
|
|
let target = devtools.TargetFactory.forTab(window.gBrowser.selectedTab);
|
2012-12-13 13:03:55 +00:00
|
|
|
let toolbox = gDevTools.getToolbox(target);
|
|
|
|
|
|
|
|
return toolbox && toolbox.currentToolId == "webconsole" ?
|
|
|
|
toolbox.destroy() :
|
|
|
|
gDevTools.showToolbox(target, "webconsole");
|
2010-06-22 16:51:50 +00:00
|
|
|
},
|
|
|
|
|
2011-04-20 08:18:00 +00:00
|
|
|
/**
|
2013-01-11 17:31:09 +00:00
|
|
|
* Find if there is a Web Console open for the current tab and return the
|
|
|
|
* instance.
|
|
|
|
* @return object|null
|
|
|
|
* The WebConsole object or null if the active tab has no open Web
|
2011-04-20 08:18:00 +00:00
|
|
|
* Console.
|
|
|
|
*/
|
2013-01-11 17:31:09 +00:00
|
|
|
getOpenHUD: function UIC_getOpenHUD()
|
2010-06-22 16:51:50 +00:00
|
|
|
{
|
2013-01-11 18:54:03 +00:00
|
|
|
let tab = HUDService.currentContext().gBrowser.selectedTab;
|
2013-04-11 20:59:08 +00:00
|
|
|
if (!tab || !devtools.TargetFactory.isKnownTab(tab)) {
|
2013-01-11 18:54:03 +00:00
|
|
|
return null;
|
|
|
|
}
|
2013-04-11 20:59:08 +00:00
|
|
|
let target = devtools.TargetFactory.forTab(tab);
|
2013-01-11 17:31:09 +00:00
|
|
|
let toolbox = gDevTools.getToolbox(target);
|
|
|
|
let panel = toolbox ? toolbox.getPanel("webconsole") : null;
|
|
|
|
return panel ? panel.hud : null;
|
2010-06-22 16:51:50 +00:00
|
|
|
},
|
2013-04-09 09:47:23 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Toggle the Browser Console.
|
|
|
|
*/
|
|
|
|
toggleBrowserConsole: function UIC_toggleBrowserConsole()
|
|
|
|
{
|
|
|
|
if (this._browserConsoleID) {
|
|
|
|
let hud = HUDService.getHudReferenceById(this._browserConsoleID);
|
|
|
|
return hud.destroy();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (this._browserConsoleDefer) {
|
|
|
|
return this._browserConsoleDefer.promise;
|
|
|
|
}
|
|
|
|
|
|
|
|
this._browserConsoleDefer = Promise.defer();
|
|
|
|
|
|
|
|
function connect()
|
|
|
|
{
|
|
|
|
let deferred = Promise.defer();
|
|
|
|
|
|
|
|
if (!DebuggerServer.initialized) {
|
|
|
|
DebuggerServer.init();
|
|
|
|
DebuggerServer.addBrowserActors();
|
|
|
|
}
|
|
|
|
|
|
|
|
let client = new DebuggerClient(DebuggerServer.connectPipe());
|
|
|
|
client.connect(() =>
|
2013-04-23 06:09:24 +00:00
|
|
|
client.listTabs((aResponse) => {
|
|
|
|
// Add Global Process debugging...
|
|
|
|
let globals = JSON.parse(JSON.stringify(aResponse));
|
|
|
|
delete globals.tabs;
|
|
|
|
delete globals.selected;
|
|
|
|
// ...only if there are appropriate actors (a 'from' property will
|
|
|
|
// always be there).
|
|
|
|
if (Object.keys(globals).length > 1) {
|
|
|
|
deferred.resolve({ form: globals, client: client, chrome: true });
|
|
|
|
} else {
|
|
|
|
deferred.reject("Global console not found!");
|
|
|
|
}
|
|
|
|
}));
|
2013-04-09 09:47:23 +00:00
|
|
|
|
|
|
|
return deferred.promise;
|
|
|
|
}
|
|
|
|
|
|
|
|
let target;
|
|
|
|
function getTarget(aConnection)
|
|
|
|
{
|
|
|
|
let options = {
|
|
|
|
form: aConnection.form,
|
|
|
|
client: aConnection.client,
|
|
|
|
chrome: true,
|
|
|
|
};
|
|
|
|
|
2013-04-11 20:59:08 +00:00
|
|
|
return devtools.TargetFactory.forRemoteTab(options);
|
2013-04-09 09:47:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
function openWindow(aTarget)
|
|
|
|
{
|
|
|
|
target = aTarget;
|
|
|
|
|
|
|
|
let deferred = Promise.defer();
|
|
|
|
|
2013-04-11 20:59:08 +00:00
|
|
|
let win = Services.ww.openWindow(null, devtools.Tools.webConsole.url, "_blank",
|
2013-04-09 09:47:23 +00:00
|
|
|
BROWSER_CONSOLE_WINDOW_FEATURES, null);
|
2013-05-30 15:08:14 +00:00
|
|
|
win.addEventListener("DOMContentLoaded", function onLoad() {
|
|
|
|
win.removeEventListener("DOMContentLoaded", onLoad);
|
|
|
|
|
|
|
|
// Set the correct Browser Console title.
|
|
|
|
let root = win.document.documentElement;
|
|
|
|
root.setAttribute("title", root.getAttribute("browserConsoleTitle"));
|
|
|
|
|
2013-04-09 09:47:23 +00:00
|
|
|
deferred.resolve(win);
|
|
|
|
});
|
|
|
|
|
|
|
|
return deferred.promise;
|
|
|
|
}
|
|
|
|
|
|
|
|
connect().then(getTarget).then(openWindow).then((aWindow) =>
|
|
|
|
HUDService.openBrowserConsole(target, aWindow, aWindow)
|
|
|
|
.then((aBrowserConsole) => {
|
|
|
|
this._browserConsoleID = aBrowserConsole.hudId;
|
|
|
|
this._browserConsoleDefer.resolve(aBrowserConsole);
|
|
|
|
this._browserConsoleDefer = null;
|
|
|
|
}));
|
|
|
|
|
|
|
|
return this._browserConsoleDefer.promise;
|
|
|
|
},
|
|
|
|
|
|
|
|
get browserConsole() {
|
|
|
|
return HUDService.getHudReferenceById(this._browserConsoleID);
|
|
|
|
},
|
2010-06-22 16:51:50 +00:00
|
|
|
};
|
|
|
|
|
2012-11-30 08:07:59 +00:00
|
|
|
const HUDService = new HUD_SERVICE();
|
2013-04-11 20:59:08 +00:00
|
|
|
|