mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 768096 - Web Console remote debugging protocol support - Part 1: page errors; r=past,robcee
--HG-- rename : browser/devtools/webconsole/WebConsoleUtils.jsm => toolkit/devtools/webconsole/WebConsoleUtils.jsm
This commit is contained in:
parent
d165fdcaaa
commit
348454ccd7
@ -11,12 +11,13 @@
|
||||
let Cc = Components.classes;
|
||||
let Ci = Components.interfaces;
|
||||
let Cu = Components.utils;
|
||||
const STRINGS_URI = "chrome://browser/locale/devtools/webconsole.properties";
|
||||
|
||||
let tempScope = {};
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm", tempScope);
|
||||
Cu.import("resource://gre/modules/Services.jsm", tempScope);
|
||||
Cu.import("resource://gre/modules/ConsoleAPIStorage.jsm", tempScope);
|
||||
Cu.import("resource:///modules/WebConsoleUtils.jsm", tempScope);
|
||||
Cu.import("resource://gre/modules/devtools/WebConsoleUtils.jsm", tempScope);
|
||||
Cu.import("resource:///modules/NetworkHelper.jsm", tempScope);
|
||||
Cu.import("resource://gre/modules/NetUtil.jsm", tempScope);
|
||||
|
||||
@ -24,7 +25,7 @@ let XPCOMUtils = tempScope.XPCOMUtils;
|
||||
let Services = tempScope.Services;
|
||||
let gConsoleStorage = tempScope.ConsoleAPIStorage;
|
||||
let WebConsoleUtils = tempScope.WebConsoleUtils;
|
||||
let l10n = WebConsoleUtils.l10n;
|
||||
let l10n = new WebConsoleUtils.l10n(STRINGS_URI);
|
||||
let JSPropertyProvider = tempScope.JSPropertyProvider;
|
||||
let NetworkHelper = tempScope.NetworkHelper;
|
||||
let NetUtil = tempScope.NetUtil;
|
||||
@ -185,6 +186,8 @@ let Manager = {
|
||||
if (aMessage.cachedMessages) {
|
||||
this._sendCachedMessages(aMessage.cachedMessages);
|
||||
}
|
||||
|
||||
this.sendMessage("WebConsole:Initialized", {});
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -18,12 +18,10 @@ XPCOMUtils.defineLazyModuleGetter(this, "Services",
|
||||
"resource://gre/modules/Services.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "WebConsoleUtils",
|
||||
"resource:///modules/WebConsoleUtils.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "l10n", function() {
|
||||
return WebConsoleUtils.l10n;
|
||||
});
|
||||
"resource://gre/modules/devtools/WebConsoleUtils.jsm");
|
||||
|
||||
const STRINGS_URI = "chrome://browser/locale/devtools/webconsole.properties";
|
||||
let l10n = new WebConsoleUtils.l10n(STRINGS_URI);
|
||||
|
||||
var EXPORTED_SYMBOLS = ["HUDService"];
|
||||
|
||||
@ -172,7 +170,10 @@ HUD_SERVICE.prototype =
|
||||
let hud = this.getHudReferenceById(hudId);
|
||||
let document = hud.chromeDocument;
|
||||
|
||||
hud.destroy();
|
||||
hud.destroy(function() {
|
||||
let id = WebConsoleUtils.supportsString(hudId);
|
||||
Services.obs.notifyObservers(id, "web-console-destroyed", null);
|
||||
});
|
||||
|
||||
delete this.hudReferences[hudId];
|
||||
|
||||
@ -199,9 +200,6 @@ HUD_SERVICE.prototype =
|
||||
contentWindow.focus();
|
||||
|
||||
HeadsUpDisplayUICommands.refreshCommand();
|
||||
|
||||
let id = WebConsoleUtils.supportsString(hudId);
|
||||
Services.obs.notifyObservers(id, "web-console-destroyed", null);
|
||||
},
|
||||
|
||||
/**
|
||||
@ -539,7 +537,7 @@ WebConsole.prototype = {
|
||||
* @type array
|
||||
*/
|
||||
_messageListeners: ["JSTerm:EvalObject", "WebConsole:ConsoleAPI",
|
||||
"WebConsole:CachedMessages", "WebConsole:PageError", "JSTerm:EvalResult",
|
||||
"WebConsole:CachedMessages", "WebConsole:Initialized", "JSTerm:EvalResult",
|
||||
"JSTerm:AutocompleteProperties", "JSTerm:ClearOutput",
|
||||
"JSTerm:InspectObject", "WebConsole:NetworkActivity",
|
||||
"WebConsole:FileActivity", "WebConsole:LocationChange",
|
||||
@ -926,8 +924,7 @@ WebConsole.prototype = {
|
||||
}, this);
|
||||
|
||||
let message = {
|
||||
features: ["ConsoleAPI", "JSTerm", "PageError", "NetworkMonitor",
|
||||
"LocationChange"],
|
||||
features: ["ConsoleAPI", "JSTerm", "NetworkMonitor", "LocationChange"],
|
||||
cachedMessages: ["ConsoleAPI", "PageError"],
|
||||
NetworkMonitor: { monitorFileActivity: true },
|
||||
JSTerm: { notifyNonNativeConsoleAPI: true },
|
||||
@ -940,19 +937,6 @@ WebConsole.prototype = {
|
||||
this.sendMessageToContent("WebConsole:Init", message);
|
||||
},
|
||||
|
||||
/**
|
||||
* Callback method for when the Web Console initialization is complete. For
|
||||
* now this method sends the web-console-created notification using the
|
||||
* nsIObserverService.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
_onInitComplete: function WC__onInitComplete()
|
||||
{
|
||||
let id = WebConsoleUtils.supportsString(this.hudId);
|
||||
Services.obs.notifyObservers(id, "web-console-created", null);
|
||||
},
|
||||
|
||||
/**
|
||||
* Handler for messages that have an associated callback function. The
|
||||
* this.sendMessageToContent() allows one to provide a function to be invoked
|
||||
@ -1051,8 +1035,12 @@ WebConsole.prototype = {
|
||||
/**
|
||||
* Destroy the object. Call this method to avoid memory leaks when the Web
|
||||
* Console is closed.
|
||||
*
|
||||
* @param function [aOnDestroy]
|
||||
* Optional function to invoke when the Web Console instance is
|
||||
* destroyed.
|
||||
*/
|
||||
destroy: function WC_destroy()
|
||||
destroy: function WC_destroy(aOnDestroy)
|
||||
{
|
||||
this.sendMessageToContent("WebConsole:Destroy", {});
|
||||
|
||||
@ -1072,24 +1060,31 @@ WebConsole.prototype = {
|
||||
}
|
||||
}
|
||||
|
||||
let onDestroy = function WC_onDestroyUI() {
|
||||
// Remove the iframe 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.iframe.parentNode) {
|
||||
this.iframe.parentNode.removeChild(this.iframe);
|
||||
}
|
||||
|
||||
if (this.splitter.parentNode) {
|
||||
this.splitter.parentNode.removeChild(this.splitter);
|
||||
}
|
||||
|
||||
aOnDestroy && aOnDestroy();
|
||||
}.bind(this);
|
||||
|
||||
if (this.ui) {
|
||||
this.ui.destroy();
|
||||
this.ui.destroy(onDestroy);
|
||||
}
|
||||
|
||||
// Remove the iframe 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.iframe.parentNode) {
|
||||
this.iframe.parentNode.removeChild(this.iframe);
|
||||
}
|
||||
|
||||
if (this.splitter.parentNode) {
|
||||
this.splitter.parentNode.removeChild(this.splitter);
|
||||
else {
|
||||
onDestroy();
|
||||
}
|
||||
},
|
||||
};
|
||||
|
@ -16,7 +16,6 @@ EXTRA_JS_MODULES = \
|
||||
NetworkHelper.jsm \
|
||||
NetworkPanel.jsm \
|
||||
AutocompletePopup.jsm \
|
||||
WebConsoleUtils.jsm \
|
||||
$(NULL)
|
||||
|
||||
TEST_DIRS = test
|
||||
|
@ -22,11 +22,10 @@ XPCOMUtils.defineLazyModuleGetter(this, "NetUtil",
|
||||
"resource://gre/modules/NetUtil.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "WebConsoleUtils",
|
||||
"resource:///modules/WebConsoleUtils.jsm");
|
||||
"resource://gre/modules/devtools/WebConsoleUtils.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "l10n", function() {
|
||||
return WebConsoleUtils.l10n;
|
||||
});
|
||||
const STRINGS_URI = "chrome://browser/locale/devtools/webconsole.properties";
|
||||
let l10n = new WebConsoleUtils.l10n(STRINGS_URI);
|
||||
|
||||
var EXPORTED_SYMBOLS = ["NetworkPanel"];
|
||||
|
||||
|
@ -13,7 +13,7 @@ const Cu = Components.utils;
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "WebConsoleUtils",
|
||||
"resource:///modules/WebConsoleUtils.jsm");
|
||||
"resource://gre/modules/devtools/WebConsoleUtils.jsm");
|
||||
|
||||
var EXPORTED_SYMBOLS = ["PropertyPanel", "PropertyTreeView"];
|
||||
|
||||
|
@ -21,7 +21,7 @@ function test() {
|
||||
browser.removeEventListener("DOMContentLoaded", testTimestamp, false);
|
||||
const TEST_TIMESTAMP = 12345678;
|
||||
let date = new Date(TEST_TIMESTAMP);
|
||||
let localizedString = WebConsoleUtils.l10n.timestampString(TEST_TIMESTAMP);
|
||||
let localizedString = WCU_l10n.timestampString(TEST_TIMESTAMP);
|
||||
isnot(localizedString.indexOf(date.getHours()), -1, "the localized " +
|
||||
"timestamp contains the hours");
|
||||
isnot(localizedString.indexOf(date.getMinutes()), -1, "the localized " +
|
||||
|
@ -81,7 +81,7 @@ function testContextMenuCopy() {
|
||||
}
|
||||
|
||||
function getExpectedClipboardText(aItem) {
|
||||
return "[" + WebConsoleUtils.l10n.timestampString(aItem.timestamp) + "] " +
|
||||
return "[" + WCU_l10n.timestampString(aItem.timestamp) + "] " +
|
||||
aItem.clipboardText;
|
||||
}
|
||||
|
||||
|
@ -14,25 +14,35 @@ let tab1, tab2, win1, win2;
|
||||
let noErrors = true;
|
||||
|
||||
function tab1Loaded(aEvent) {
|
||||
browser.removeEventListener(aEvent.type, arguments.callee, true);
|
||||
browser.removeEventListener(aEvent.type, tab1Loaded, true);
|
||||
|
||||
win2 = OpenBrowserWindow();
|
||||
win2.addEventListener("load", win2Loaded, true);
|
||||
}
|
||||
|
||||
function win2Loaded(aEvent) {
|
||||
win2.removeEventListener(aEvent.type, arguments.callee, true);
|
||||
win2.removeEventListener(aEvent.type, win2Loaded, true);
|
||||
|
||||
tab2 = win2.gBrowser.addTab();
|
||||
tab2 = win2.gBrowser.addTab(TEST_URI);
|
||||
win2.gBrowser.selectedTab = tab2;
|
||||
tab2.linkedBrowser.addEventListener("load", tab2Loaded, true);
|
||||
tab2.linkedBrowser.contentWindow.location = TEST_URI;
|
||||
}
|
||||
|
||||
function tab2Loaded(aEvent) {
|
||||
tab2.linkedBrowser.removeEventListener(aEvent.type, arguments.callee, true);
|
||||
tab2.linkedBrowser.removeEventListener(aEvent.type, tab2Loaded, true);
|
||||
|
||||
waitForFocus(function() {
|
||||
let consolesOpened = 0;
|
||||
function onWebConsoleOpen() {
|
||||
consolesOpened++;
|
||||
if (consolesOpened == 2) {
|
||||
Services.obs.removeObserver(onWebConsoleOpen, "web-console-created");
|
||||
executeSoon(closeConsoles);
|
||||
}
|
||||
}
|
||||
|
||||
Services.obs.addObserver(onWebConsoleOpen, "web-console-created", false);
|
||||
|
||||
function openConsoles() {
|
||||
try {
|
||||
HUDService.activateHUDForContext(tab1);
|
||||
}
|
||||
@ -48,6 +58,20 @@ function tab2Loaded(aEvent) {
|
||||
ok(false, "HUDService.activateHUDForContext(tab2) exception: " + ex);
|
||||
noErrors = false;
|
||||
}
|
||||
}
|
||||
|
||||
let consolesClosed = 0;
|
||||
function onWebConsoleClose()
|
||||
{
|
||||
consolesClosed++;
|
||||
if (consolesClosed == 2) {
|
||||
Services.obs.removeObserver(onWebConsoleClose, "web-console-destroyed");
|
||||
executeSoon(testEnd);
|
||||
}
|
||||
}
|
||||
|
||||
function closeConsoles() {
|
||||
Services.obs.addObserver(onWebConsoleClose, "web-console-destroyed", false);
|
||||
|
||||
try {
|
||||
HUDService.deactivateHUDForContext(tab1);
|
||||
@ -64,20 +88,26 @@ function tab2Loaded(aEvent) {
|
||||
ok(false, "HUDService.deactivateHUDForContext(tab2) exception: " + ex);
|
||||
noErrors = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (noErrors) {
|
||||
ok(true, "there were no errors");
|
||||
}
|
||||
function testEnd() {
|
||||
ok(noErrors, "there were no errors");
|
||||
|
||||
win2.gBrowser.removeTab(tab2);
|
||||
Array.forEach(win1.gBrowser.tabs, function(aTab) {
|
||||
win1.gBrowser.removeTab(aTab);
|
||||
});
|
||||
Array.forEach(win2.gBrowser.tabs, function(aTab) {
|
||||
win2.gBrowser.removeTab(aTab);
|
||||
});
|
||||
|
||||
executeSoon(function() {
|
||||
win2.close();
|
||||
tab1 = tab2 = win1 = win2 = null;
|
||||
finishTest();
|
||||
});
|
||||
}
|
||||
|
||||
}, tab2.linkedBrowser.contentWindow);
|
||||
waitForFocus(openConsoles, tab2.linkedBrowser.contentWindow);
|
||||
}
|
||||
|
||||
function test() {
|
||||
|
@ -16,14 +16,14 @@ const MINIMUM_CONSOLE_HEIGHT = 150;
|
||||
const MINIMUM_PAGE_HEIGHT = 50;
|
||||
const HEIGHT_PREF = "devtools.hud.height";
|
||||
|
||||
let hud, newHeight, height, innerHeight;
|
||||
let hud, newHeight, height, innerHeight, testDriver;
|
||||
|
||||
function performTests(aWebConsole)
|
||||
function testGen()
|
||||
{
|
||||
hud = aWebConsole.iframe;
|
||||
height = parseInt(hud.style.height);
|
||||
|
||||
toggleConsole();
|
||||
yield;
|
||||
|
||||
is(newHeight, height, "same height after reopening the console");
|
||||
is(Services.prefs.getIntPref(HEIGHT_PREF), HUDService.lastConsoleHeight,
|
||||
@ -31,6 +31,7 @@ function performTests(aWebConsole)
|
||||
|
||||
setHeight(Math.ceil(innerHeight * 0.5));
|
||||
toggleConsole();
|
||||
yield;
|
||||
|
||||
is(newHeight, height, "same height after reopening the console");
|
||||
is(Services.prefs.getIntPref(HEIGHT_PREF), HUDService.lastConsoleHeight,
|
||||
@ -38,6 +39,7 @@ function performTests(aWebConsole)
|
||||
|
||||
setHeight(MINIMUM_CONSOLE_HEIGHT - 1);
|
||||
toggleConsole();
|
||||
yield;
|
||||
|
||||
is(newHeight, MINIMUM_CONSOLE_HEIGHT, "minimum console height is respected");
|
||||
is(Services.prefs.getIntPref(HEIGHT_PREF), HUDService.lastConsoleHeight,
|
||||
@ -45,6 +47,7 @@ function performTests(aWebConsole)
|
||||
|
||||
setHeight(innerHeight - MINIMUM_PAGE_HEIGHT + 1);
|
||||
toggleConsole();
|
||||
yield;
|
||||
|
||||
is(newHeight, innerHeight - MINIMUM_PAGE_HEIGHT,
|
||||
"minimum page height is respected");
|
||||
@ -54,6 +57,7 @@ function performTests(aWebConsole)
|
||||
setHeight(Math.ceil(innerHeight * 0.6));
|
||||
Services.prefs.setIntPref(HEIGHT_PREF, -1);
|
||||
toggleConsole();
|
||||
yield;
|
||||
|
||||
is(newHeight, height, "same height after reopening the console");
|
||||
is(Services.prefs.getIntPref(HEIGHT_PREF), -1, "pref is not updated");
|
||||
@ -62,17 +66,23 @@ function performTests(aWebConsole)
|
||||
HUDService.lastConsoleHeight = 0;
|
||||
Services.prefs.setIntPref(HEIGHT_PREF, 0);
|
||||
|
||||
hud = testDriver = null;
|
||||
executeSoon(finishTest);
|
||||
|
||||
yield;
|
||||
}
|
||||
|
||||
function toggleConsole()
|
||||
{
|
||||
closeConsole();
|
||||
openConsole();
|
||||
closeConsole(null, function() {
|
||||
openConsole(null, function() {
|
||||
let hudId = HUDService.getHudIdByWindow(content);
|
||||
hud = HUDService.hudReferences[hudId].iframe;
|
||||
newHeight = parseInt(hud.style.height);
|
||||
|
||||
let hudId = HUDService.getHudIdByWindow(content);
|
||||
hud = HUDService.hudReferences[hudId].iframe;
|
||||
newHeight = parseInt(hud.style.height);
|
||||
testDriver.next();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function setHeight(aHeight)
|
||||
@ -87,7 +97,11 @@ function test()
|
||||
browser.addEventListener("load", function onLoad() {
|
||||
browser.removeEventListener("load", onLoad, true);
|
||||
innerHeight = content.innerHeight;
|
||||
openConsole(null, performTests);
|
||||
openConsole(null, function(aHud) {
|
||||
hud = aHud.iframe;
|
||||
testDriver = testGen();
|
||||
testDriver.next();
|
||||
});
|
||||
}, true);
|
||||
}
|
||||
|
||||
|
@ -80,6 +80,6 @@ function performTest(HUD) {
|
||||
}
|
||||
|
||||
function getExpectedClipboardText(aItem) {
|
||||
return "[" + WebConsoleUtils.l10n.timestampString(aItem.timestamp) + "] " +
|
||||
return "[" + WCU_l10n.timestampString(aItem.timestamp) + "] " +
|
||||
aItem.clipboardText;
|
||||
}
|
||||
|
@ -58,7 +58,7 @@ function getExpectedClipboardText(aItemCount) {
|
||||
for (let i = 0; i < aItemCount; i++) {
|
||||
let item = outputNode.getItemAtIndex(i);
|
||||
expectedClipboardText.push("[" +
|
||||
WebConsoleUtils.l10n.timestampString(item.timestamp) + "] " +
|
||||
WCU_l10n.timestampString(item.timestamp) + "] " +
|
||||
item.clipboardText);
|
||||
}
|
||||
return expectedClipboardText.join("\n");
|
||||
|
@ -15,7 +15,7 @@ function test() {
|
||||
|
||||
function consoleOpened(HUD) {
|
||||
let tmp = {};
|
||||
Cu.import("resource:///modules/WebConsoleUtils.jsm", tmp);
|
||||
Cu.import("resource://gre/modules/devtools/WebConsoleUtils.jsm", tmp);
|
||||
let WCU = tmp.WebConsoleUtils;
|
||||
let JSPropertyProvider = tmp.JSPropertyProvider;
|
||||
tmp = null;
|
||||
|
@ -23,7 +23,7 @@ function consoleOpened(aHud) {
|
||||
let completeNode = jsterm.completeNode;
|
||||
|
||||
let tmp = {};
|
||||
Cu.import("resource:///modules/WebConsoleUtils.jsm", tmp);
|
||||
Cu.import("resource://gre/modules/devtools/WebConsoleUtils.jsm", tmp);
|
||||
let WCU = tmp.WebConsoleUtils;
|
||||
tmp = null;
|
||||
|
||||
|
@ -6,7 +6,7 @@
|
||||
// Tests that code completion works properly.
|
||||
|
||||
function test() {
|
||||
addTab("about:addons");
|
||||
addTab("about:credits");
|
||||
browser.addEventListener("load", function onLoad() {
|
||||
browser.removeEventListener("load", onLoad, true);
|
||||
openConsole(null, testChrome);
|
||||
@ -15,7 +15,7 @@ function test() {
|
||||
|
||||
function testChrome(hud) {
|
||||
ok(hud, "we have a console");
|
||||
|
||||
|
||||
ok(hud.iframe, "we have the console iframe");
|
||||
|
||||
let jsterm = hud.jsterm;
|
||||
|
@ -52,7 +52,7 @@ function testClipboard() {
|
||||
for (let i = 0; i < outputNode.itemCount; i++) {
|
||||
let item = outputNode.getItemAtIndex(i);
|
||||
clipboardTexts.push("[" +
|
||||
WebConsoleUtils.l10n.timestampString(item.timestamp) +
|
||||
WCU_l10n.timestampString(item.timestamp) +
|
||||
"] " + item.clipboardText);
|
||||
}
|
||||
|
||||
|
@ -64,11 +64,6 @@ function testGen() {
|
||||
let hud = HUDService.getHudByWindow(content);
|
||||
let filterBox = hud.ui.filterBox;
|
||||
|
||||
let tempScope = {};
|
||||
Cu.import("resource:///modules/WebConsoleUtils.jsm", tempScope);
|
||||
let l10n = tempScope.WebConsoleUtils.l10n;
|
||||
tempScope = null;
|
||||
|
||||
let httpActivity = {
|
||||
meta: {
|
||||
stages: [],
|
||||
@ -442,7 +437,7 @@ function testGen() {
|
||||
});
|
||||
|
||||
let responseString =
|
||||
l10n.getFormatStr("NetworkPanel.responseBodyUnableToDisplay.content",
|
||||
WCU_l10n.getFormatStr("NetworkPanel.responseBodyUnableToDisplay.content",
|
||||
["application/x-shockwave-flash"]);
|
||||
checkNodeContent(networkPanel, "responseBodyUnknownTypeContent", responseString);
|
||||
networkPanel.panel.hidePopup();
|
||||
|
@ -17,7 +17,7 @@ function testPropertyProvider() {
|
||||
browser.removeEventListener("load", testPropertyProvider, true);
|
||||
|
||||
let tmp = {};
|
||||
Cu.import("resource:///modules/WebConsoleUtils.jsm", tmp);
|
||||
Cu.import("resource://gre/modules/devtools/WebConsoleUtils.jsm", tmp);
|
||||
let JSPropertyProvider = tmp.JSPropertyProvider;
|
||||
tmp = null;
|
||||
|
||||
|
@ -6,8 +6,10 @@
|
||||
let tempScope = {};
|
||||
Cu.import("resource:///modules/HUDService.jsm", tempScope);
|
||||
let HUDService = tempScope.HUDService;
|
||||
Cu.import("resource:///modules/WebConsoleUtils.jsm", tempScope);
|
||||
Cu.import("resource://gre/modules/devtools/WebConsoleUtils.jsm", tempScope);
|
||||
let WebConsoleUtils = tempScope.WebConsoleUtils;
|
||||
const WEBCONSOLE_STRINGS_URI = "chrome://browser/locale/devtools/webconsole.properties";
|
||||
let WCU_l10n = new WebConsoleUtils.l10n(WEBCONSOLE_STRINGS_URI);
|
||||
|
||||
function log(aMsg)
|
||||
{
|
||||
@ -252,7 +254,7 @@ function tearDown()
|
||||
while (gBrowser.tabs.length > 1) {
|
||||
gBrowser.removeCurrentTab();
|
||||
}
|
||||
tab = browser = hudId = hud = filterBox = outputNode = cs = null;
|
||||
WCU_l10n = tab = browser = hudId = hud = filterBox = outputNode = cs = null;
|
||||
}
|
||||
|
||||
registerCleanupFunction(tearDown);
|
||||
|
@ -15,6 +15,12 @@ Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "Services",
|
||||
"resource://gre/modules/Services.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "DebuggerServer",
|
||||
"resource://gre/modules/devtools/dbg-server.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "DebuggerClient",
|
||||
"resource://gre/modules/devtools/dbg-client.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "clipboardHelper",
|
||||
"@mozilla.org/widget/clipboardhelper;1",
|
||||
"nsIClipboardHelper");
|
||||
@ -32,11 +38,10 @@ XPCOMUtils.defineLazyModuleGetter(this, "AutocompletePopup",
|
||||
"resource:///modules/AutocompletePopup.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "WebConsoleUtils",
|
||||
"resource:///modules/WebConsoleUtils.jsm");
|
||||
"resource://gre/modules/devtools/WebConsoleUtils.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "l10n", function() {
|
||||
return WebConsoleUtils.l10n;
|
||||
});
|
||||
const STRINGS_URI = "chrome://browser/locale/devtools/webconsole.properties";
|
||||
let l10n = new WebConsoleUtils.l10n(STRINGS_URI);
|
||||
|
||||
|
||||
// The XUL namespace.
|
||||
@ -187,6 +192,8 @@ function WebConsoleFrame(aWebConsoleOwner, aPosition)
|
||||
|
||||
this.jsterm = new JSTerm(this);
|
||||
this.jsterm.inputNode.focus();
|
||||
|
||||
this._initConnection();
|
||||
}
|
||||
|
||||
WebConsoleFrame.prototype = {
|
||||
@ -197,6 +204,23 @@ WebConsoleFrame.prototype = {
|
||||
*/
|
||||
owner: null,
|
||||
|
||||
/**
|
||||
* Proxy between the Web Console and the remote Web Console instance. This
|
||||
* object holds methods used for connecting, listening and disconnecting from
|
||||
* the remote server, using the remote debugging protocol.
|
||||
*
|
||||
* @see WebConsoleConnectionProxy
|
||||
* @type object
|
||||
*/
|
||||
proxy: null,
|
||||
|
||||
/**
|
||||
* Tells if the Web Console initialization via message manager completed.
|
||||
* @private
|
||||
* @type boolean
|
||||
*/
|
||||
_messageManagerInitComplete: false,
|
||||
|
||||
/**
|
||||
* Getter for the xul:popupset that holds any popups we open.
|
||||
* @type nsIDOMElement
|
||||
@ -311,6 +335,21 @@ WebConsoleFrame.prototype = {
|
||||
this.owner.sendMessageToContent("WebConsole:SetPreferences", message);
|
||||
},
|
||||
|
||||
/**
|
||||
* Connect to the server using the remote debugging protocol.
|
||||
* @private
|
||||
*/
|
||||
_initConnection: function WCF__initConnection()
|
||||
{
|
||||
this.proxy = new WebConsoleConnectionProxy(this);
|
||||
this.proxy.initServer();
|
||||
this.proxy.connect(function() {
|
||||
if (this._messageManagerInitComplete) {
|
||||
this._onInitComplete();
|
||||
}
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
/**
|
||||
* Find the Web Console UI elements and setup event listeners as needed.
|
||||
* @private
|
||||
@ -486,6 +525,19 @@ WebConsoleFrame.prototype = {
|
||||
}, this);
|
||||
},
|
||||
|
||||
/**
|
||||
* Callback method for when the Web Console initialization is complete. For
|
||||
* now this method sends the web-console-created notification using the
|
||||
* nsIObserverService.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
_onInitComplete: function WC__onInitComplete()
|
||||
{
|
||||
let id = WebConsoleUtils.supportsString(this.hudId);
|
||||
Services.obs.notifyObservers(id, "web-console-created", null);
|
||||
},
|
||||
|
||||
/**
|
||||
* Handle the "command" event for the buttons that allow the user to
|
||||
* reposition the Web Console UI.
|
||||
@ -620,16 +672,11 @@ WebConsoleFrame.prototype = {
|
||||
this.outputMessage(CATEGORY_WEBDEV, this.logConsoleAPIMessage,
|
||||
[aMessage.json]);
|
||||
break;
|
||||
case "WebConsole:PageError": {
|
||||
let pageError = aMessage.json.pageError;
|
||||
let category = Utils.categoryForScriptError(pageError);
|
||||
this.outputMessage(category, this.reportPageError,
|
||||
[category, pageError]);
|
||||
case "WebConsole:Initialized":
|
||||
this._onMessageManagerInitComplete();
|
||||
break;
|
||||
}
|
||||
case "WebConsole:CachedMessages":
|
||||
this._displayCachedConsoleMessages(aMessage.json.messages);
|
||||
this.owner._onInitComplete();
|
||||
break;
|
||||
case "WebConsole:NetworkActivity":
|
||||
this.handleNetworkActivity(aMessage.json);
|
||||
@ -647,6 +694,20 @@ WebConsoleFrame.prototype = {
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Callback method used to track the Web Console initialization via message
|
||||
* manager.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
_onMessageManagerInitComplete: function WCF__onMessageManagerInitComplete()
|
||||
{
|
||||
this._messageManagerInitComplete = true;
|
||||
if (this.proxy.connected) {
|
||||
this._onInitComplete();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* The event handler that is called whenever a user switches a filter on or
|
||||
* off.
|
||||
@ -1226,8 +1287,7 @@ WebConsoleFrame.prototype = {
|
||||
// Warnings and legacy strict errors become warnings; other types become
|
||||
// errors.
|
||||
let severity = SEVERITY_ERROR;
|
||||
if ((aScriptError.flags & aScriptError.warningFlag) ||
|
||||
(aScriptError.flags & aScriptError.strictFlag)) {
|
||||
if (aScriptError.warning || aScriptError.strict) {
|
||||
severity = SEVERITY_WARNING;
|
||||
}
|
||||
|
||||
@ -1239,6 +1299,19 @@ WebConsoleFrame.prototype = {
|
||||
return node;
|
||||
},
|
||||
|
||||
/**
|
||||
* Handle PageError objects received from the server. This method outputs the
|
||||
* given error.
|
||||
*
|
||||
* @param nsIScriptError aPageError
|
||||
* The error received from the server.
|
||||
*/
|
||||
handlePageError: function WCF_handlePageError(aPageError)
|
||||
{
|
||||
let category = Utils.categoryForScriptError(aPageError);
|
||||
this.outputMessage(category, this.reportPageError, [category, aPageError]);
|
||||
},
|
||||
|
||||
/**
|
||||
* Log network activity.
|
||||
*
|
||||
@ -2337,9 +2410,17 @@ WebConsoleFrame.prototype = {
|
||||
/**
|
||||
* Destroy the HUD object. Call this method to avoid memory leaks when the Web
|
||||
* Console is closed.
|
||||
*
|
||||
* @param function [aOnDestroy]
|
||||
* Optional function to invoke when the Web Console instance is
|
||||
* destroyed.
|
||||
*/
|
||||
destroy: function WCF_destroy()
|
||||
destroy: function WCF_destroy(aOnDestroy)
|
||||
{
|
||||
if (this.proxy) {
|
||||
this.proxy.disconnect(aOnDestroy);
|
||||
}
|
||||
|
||||
if (this.jsterm) {
|
||||
this.jsterm.destroy();
|
||||
}
|
||||
@ -3535,6 +3616,158 @@ CommandController.prototype = {
|
||||
}
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Web Console connection proxy
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* The WebConsoleConnectionProxy handles the connection between the Web Console
|
||||
* and the application we connect to through the remote debug protocol.
|
||||
*
|
||||
* @constructor
|
||||
* @param object aWebConsole
|
||||
* The Web Console instance that owns this connection proxy.
|
||||
*/
|
||||
function WebConsoleConnectionProxy(aWebConsole)
|
||||
{
|
||||
this.owner = aWebConsole;
|
||||
|
||||
this._onPageError = this._onPageError.bind(this);
|
||||
}
|
||||
|
||||
WebConsoleConnectionProxy.prototype = {
|
||||
/**
|
||||
* The owning Web Console instance.
|
||||
*
|
||||
* @see WebConsoleFrame
|
||||
* @type object
|
||||
*/
|
||||
owner: null,
|
||||
|
||||
/**
|
||||
* The DebuggerClient object.
|
||||
*
|
||||
* @see DebuggerClient
|
||||
* @type object
|
||||
*/
|
||||
client: null,
|
||||
|
||||
/**
|
||||
* Tells if the connection is established.
|
||||
* @type boolean
|
||||
*/
|
||||
connected: false,
|
||||
|
||||
/**
|
||||
* The WebConsoleActor ID.
|
||||
*
|
||||
* @private
|
||||
* @type string
|
||||
*/
|
||||
_consoleActor: null,
|
||||
|
||||
/**
|
||||
* Initialize the debugger server.
|
||||
*/
|
||||
initServer: function WCCP_initServer()
|
||||
{
|
||||
if (!DebuggerServer.initialized) {
|
||||
DebuggerServer.init();
|
||||
DebuggerServer.addBrowserActors();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Initialize a debugger client and connect it to the debugger server.
|
||||
*
|
||||
* @param function [aCallback]
|
||||
* Optional function to invoke when connection is established.
|
||||
*/
|
||||
connect: function WCCP_connect(aCallback)
|
||||
{
|
||||
let transport = DebuggerServer.connectPipe();
|
||||
let client = this.client = new DebuggerClient(transport);
|
||||
|
||||
client.addListener("pageError", this._onPageError);
|
||||
|
||||
let listeners = ["PageError"];
|
||||
|
||||
client.connect(function(aType, aTraits) {
|
||||
client.listTabs(function(aResponse) {
|
||||
let tab = aResponse.tabs[aResponse.selected];
|
||||
this._consoleActor = tab.consoleActor;
|
||||
client.attachConsole(tab.consoleActor, listeners,
|
||||
this._onAttachConsole.bind(this, aCallback));
|
||||
}.bind(this));
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
/**
|
||||
* The "attachConsole" response handler.
|
||||
*
|
||||
* @private
|
||||
* @param function [aCallback]
|
||||
* Optional function to invoke once the connection is established.
|
||||
* @param object aResponse
|
||||
* The JSON response object received from the server.
|
||||
* @param object aWebConsoleClient
|
||||
* The WebConsoleClient instance for the attached console, for the
|
||||
* specific tab we work with.
|
||||
*/
|
||||
_onAttachConsole:
|
||||
function WCCP__onAttachConsole(aCallback, aResponse, aWebConsoleClient)
|
||||
{
|
||||
if (aResponse.error) {
|
||||
Cu.reportError("attachConsole failed: " + aResponse.error + " " +
|
||||
aResponse.message);
|
||||
return;
|
||||
}
|
||||
|
||||
this.webConsoleClient = aWebConsoleClient;
|
||||
|
||||
this.connected = true;
|
||||
aCallback && aCallback();
|
||||
},
|
||||
|
||||
/**
|
||||
* The "pageError" message type handler. We redirect any page errors to the UI
|
||||
* for displaying.
|
||||
*
|
||||
* @private
|
||||
* @param string aType
|
||||
* Message type.
|
||||
* @param object aPacket
|
||||
* The message received from the server.
|
||||
*/
|
||||
_onPageError: function WCCP__onPageError(aType, aPacket)
|
||||
{
|
||||
if (this.owner && aPacket.from == this._consoleActor) {
|
||||
this.owner.handlePageError(aPacket.pageError);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Disconnect the Web Console from the remote server.
|
||||
*
|
||||
* @param function [aOnDisconnect]
|
||||
* Optional function to invoke when the connection is dropped.
|
||||
*/
|
||||
disconnect: function WCCP_disconnect(aOnDisconnect)
|
||||
{
|
||||
if (!this.client) {
|
||||
aOnDisconnect && aOnDisconnect();
|
||||
return;
|
||||
}
|
||||
|
||||
this.client.removeListener("pageError", this._onPageError);
|
||||
this.client.close(aOnDisconnect);
|
||||
|
||||
this.client = null;
|
||||
this.webConsoleClient = null;
|
||||
this.connected = false;
|
||||
},
|
||||
};
|
||||
|
||||
function gSequenceId()
|
||||
{
|
||||
return gSequenceId.n++;
|
||||
|
@ -12,6 +12,7 @@ include $(topsrcdir)/config/config.mk
|
||||
PARALLEL_DIRS += \
|
||||
debugger \
|
||||
sourcemap \
|
||||
webconsole \
|
||||
$(NULL)
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
@ -22,6 +22,9 @@ XPCOMUtils.defineLazyServiceGetter(this, "socketTransportService",
|
||||
"@mozilla.org/network/socket-transport-service;1",
|
||||
"nsISocketTransportService");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "WebConsoleClient",
|
||||
"resource://gre/modules/devtools/WebConsoleClient.jsm");
|
||||
|
||||
let wantLogging = Services.prefs.getBoolPref("devtools.debugger.log");
|
||||
|
||||
function dumpn(str)
|
||||
@ -167,6 +170,7 @@ const UnsolicitedNotifications = {
|
||||
"newScript": "newScript",
|
||||
"tabDetached": "tabDetached",
|
||||
"tabNavigated": "tabNavigated",
|
||||
"pageError": "pageError",
|
||||
"profilerStateChanged": "profilerStateChanged"
|
||||
};
|
||||
|
||||
@ -194,6 +198,7 @@ function DebuggerClient(aTransport)
|
||||
this._transport.hooks = this;
|
||||
this._threadClients = {};
|
||||
this._tabClients = {};
|
||||
this._consoleClients = {};
|
||||
|
||||
this._pendingRequests = [];
|
||||
this._activeRequests = {};
|
||||
@ -249,10 +254,32 @@ DebuggerClient.prototype = {
|
||||
}
|
||||
}.bind(this);
|
||||
|
||||
if (this.activeThread) {
|
||||
this.activeThread.detach(detachTab);
|
||||
} else {
|
||||
detachTab();
|
||||
let detachThread = function _detachThread() {
|
||||
if (this.activeThread) {
|
||||
this.activeThread.detach(detachTab);
|
||||
} else {
|
||||
detachTab();
|
||||
}
|
||||
}.bind(this);
|
||||
|
||||
let consolesClosed = 0;
|
||||
let consolesToClose = 0;
|
||||
|
||||
let onConsoleClose = function _onConsoleClose() {
|
||||
consolesClosed++;
|
||||
if (consolesClosed >= consolesToClose) {
|
||||
this._consoleClients = {};
|
||||
detachThread();
|
||||
}
|
||||
}.bind(this);
|
||||
|
||||
for each (let client in this._consoleClients) {
|
||||
consolesToClose++;
|
||||
client.close(onConsoleClose);
|
||||
}
|
||||
|
||||
if (!consolesToClose) {
|
||||
detachThread();
|
||||
}
|
||||
},
|
||||
|
||||
@ -282,8 +309,9 @@ DebuggerClient.prototype = {
|
||||
let self = this;
|
||||
let packet = { to: aTabActor, type: "attach" };
|
||||
this.request(packet, function(aResponse) {
|
||||
let tabClient;
|
||||
if (!aResponse.error) {
|
||||
var tabClient = new TabClient(self, aTabActor);
|
||||
tabClient = new TabClient(self, aTabActor);
|
||||
self._tabClients[aTabActor] = tabClient;
|
||||
self.activeTab = tabClient;
|
||||
}
|
||||
@ -291,6 +319,36 @@ DebuggerClient.prototype = {
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Attach to a Web Console actor.
|
||||
*
|
||||
* @param string aConsoleActor
|
||||
* The ID for the console actor to attach to.
|
||||
* @param array aListeners
|
||||
* The console listeners you want to start.
|
||||
* @param function aOnResponse
|
||||
* Called with the response packet and a WebConsoleClient
|
||||
* instance (which will be undefined on error).
|
||||
*/
|
||||
attachConsole:
|
||||
function DC_attachConsole(aConsoleActor, aListeners, aOnResponse) {
|
||||
let self = this;
|
||||
let packet = {
|
||||
to: aConsoleActor,
|
||||
type: "startListeners",
|
||||
listeners: aListeners,
|
||||
};
|
||||
|
||||
this.request(packet, function(aResponse) {
|
||||
let consoleClient;
|
||||
if (!aResponse.error) {
|
||||
consoleClient = new WebConsoleClient(self, aConsoleActor);
|
||||
self._consoleClients[aConsoleActor] = consoleClient;
|
||||
}
|
||||
aOnResponse(aResponse, consoleClient);
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Attach to a thread actor.
|
||||
*
|
||||
|
@ -185,6 +185,8 @@ var DebuggerServer = {
|
||||
*/
|
||||
addBrowserActors: function DH_addBrowserActors() {
|
||||
this.addActors("chrome://global/content/devtools/dbg-browser-actors.js");
|
||||
this.addActors("chrome://global/content/devtools/dbg-webconsole-actors.js");
|
||||
this.addTabActor(this.WebConsoleActor, "consoleActor");
|
||||
if ("nsIProfiler" in Ci)
|
||||
this.addActors("chrome://global/content/devtools/dbg-profiler-actors.js");
|
||||
},
|
||||
|
@ -7,4 +7,5 @@ toolkit.jar:
|
||||
content/global/devtools/dbg-server.js (debugger/server/dbg-server.js)
|
||||
content/global/devtools/dbg-script-actors.js (debugger/server/dbg-script-actors.js)
|
||||
content/global/devtools/dbg-browser-actors.js (debugger/server/dbg-browser-actors.js)
|
||||
content/global/devtools/dbg-webconsole-actors.js (webconsole/dbg-webconsole-actors.js)
|
||||
content/global/devtools/dbg-profiler-actors.js (debugger/server/dbg-profiler-actors.js)
|
||||
|
17
toolkit/devtools/webconsole/Makefile.in
Normal file
17
toolkit/devtools/webconsole/Makefile.in
Normal file
@ -0,0 +1,17 @@
|
||||
# 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/.
|
||||
|
||||
DEPTH = ../../..
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
#TEST_DIRS += tests
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
libs::
|
||||
$(INSTALL) $(IFLAGS1) $(srcdir)/*.jsm $(FINAL_TARGET)/modules/devtools
|
103
toolkit/devtools/webconsole/WebConsoleClient.jsm
Normal file
103
toolkit/devtools/webconsole/WebConsoleClient.jsm
Normal file
@ -0,0 +1,103 @@
|
||||
/* -*- Mode: js2; js2-basic-offset: 2; indent-tabs-mode: nil; -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* 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/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
const Cu = Components.utils;
|
||||
|
||||
var EXPORTED_SYMBOLS = ["WebConsoleClient"];
|
||||
|
||||
/**
|
||||
* A WebConsoleClient is used as a front end for the WebConsoleActor that is
|
||||
* created on the server, hiding implementation details.
|
||||
*
|
||||
* @param object aDebuggerClient
|
||||
* The DebuggerClient instance we live for.
|
||||
* @param string aActor
|
||||
* The WebConsoleActor ID.
|
||||
*/
|
||||
function WebConsoleClient(aDebuggerClient, aActor)
|
||||
{
|
||||
this._actor = aActor;
|
||||
this._client = aDebuggerClient;
|
||||
}
|
||||
|
||||
WebConsoleClient.prototype = {
|
||||
/**
|
||||
* Retrieve the cached messages from the server.
|
||||
*
|
||||
* @see this.CACHED_MESSAGES
|
||||
* @param array aTypes
|
||||
* The array of message types you want from the server. See
|
||||
* this.CACHED_MESSAGES for known types.
|
||||
* @param function aOnResponse
|
||||
* The function invoked when the response is received.
|
||||
*/
|
||||
getCachedMessages: function WCC_getCachedMessages(aTypes, aOnResponse)
|
||||
{
|
||||
let packet = {
|
||||
to: this._actor,
|
||||
type: "getCachedMessages",
|
||||
messageTypes: aTypes,
|
||||
};
|
||||
this._client.request(packet, aOnResponse);
|
||||
},
|
||||
|
||||
/**
|
||||
* Start the given Web Console listeners.
|
||||
*
|
||||
* @see this.LISTENERS
|
||||
* @param array aListeners
|
||||
* Array of listeners you want to start. See this.LISTENERS for
|
||||
* known listeners.
|
||||
* @param function aOnResponse
|
||||
* Function to invoke when the server response is received.
|
||||
*/
|
||||
startListeners: function WCC_startListeners(aListeners, aOnResponse)
|
||||
{
|
||||
let packet = {
|
||||
to: this._actor,
|
||||
type: "startListeners",
|
||||
listeners: aListeners,
|
||||
};
|
||||
this._client.request(packet, aOnResponse);
|
||||
},
|
||||
|
||||
/**
|
||||
* Stop the given Web Console listeners.
|
||||
*
|
||||
* @see this.LISTENERS
|
||||
* @param array aListeners
|
||||
* Array of listeners you want to stop. See this.LISTENERS for
|
||||
* known listeners.
|
||||
* @param function aOnResponse
|
||||
* Function to invoke when the server response is received.
|
||||
*/
|
||||
stopListeners: function WCC_stopListeners(aListeners, aOnResponse)
|
||||
{
|
||||
let packet = {
|
||||
to: this._actor,
|
||||
type: "stopListeners",
|
||||
listeners: aListeners,
|
||||
};
|
||||
this._client.request(packet, aOnResponse);
|
||||
},
|
||||
|
||||
/**
|
||||
* Close the WebConsoleClient. This stops all the listeners on the server and
|
||||
* detaches from the console actor.
|
||||
*
|
||||
* @param function aOnResponse
|
||||
* Function to invoke when the server response is received.
|
||||
*/
|
||||
close: function WCC_close(aOnResponse)
|
||||
{
|
||||
this.stopListeners(null, aOnResponse);
|
||||
this._client = null;
|
||||
},
|
||||
};
|
@ -15,9 +15,8 @@ Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "Services",
|
||||
"resource://gre/modules/Services.jsm");
|
||||
|
||||
var EXPORTED_SYMBOLS = ["WebConsoleUtils", "JSPropertyProvider"];
|
||||
|
||||
const STRINGS_URI = "chrome://browser/locale/devtools/webconsole.properties";
|
||||
var EXPORTED_SYMBOLS = ["WebConsoleUtils", "JSPropertyProvider",
|
||||
"PageErrorListener"];
|
||||
|
||||
const TYPES = { OBJECT: 0,
|
||||
FUNCTION: 1,
|
||||
@ -645,7 +644,22 @@ var WebConsoleUtils = {
|
||||
// Localization
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
WebConsoleUtils.l10n = {
|
||||
WebConsoleUtils.l10n = function WCU_l10n(aBundleURI)
|
||||
{
|
||||
this._bundleUri = aBundleURI;
|
||||
};
|
||||
|
||||
WebConsoleUtils.l10n.prototype = {
|
||||
_stringBundle: null,
|
||||
|
||||
get stringBundle()
|
||||
{
|
||||
if (!this._stringBundle) {
|
||||
this._stringBundle = Services.strings.createBundle(this._bundleUri);
|
||||
}
|
||||
return this._stringBundle;
|
||||
},
|
||||
|
||||
/**
|
||||
* Generates a formatted timestamp string for displaying in console messages.
|
||||
*
|
||||
@ -710,10 +724,6 @@ WebConsoleUtils.l10n = {
|
||||
},
|
||||
};
|
||||
|
||||
XPCOMUtils.defineLazyGetter(WebConsoleUtils.l10n, "stringBundle", function() {
|
||||
return Services.strings.createBundle(STRINGS_URI);
|
||||
});
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// JS Completer
|
||||
@ -1012,3 +1022,144 @@ function getMatchedProps(aObj, aOptions = {matchProp: ""})
|
||||
|
||||
return JSPropertyProvider;
|
||||
})(WebConsoleUtils);
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// The page errors listener
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* The nsIConsoleService listener. This is used to send all the page errors
|
||||
* (JavaScript, CSS and more) to the remote Web Console instance.
|
||||
*
|
||||
* @constructor
|
||||
* @param nsIDOMWindow aWindow
|
||||
* The window object for which we are created.
|
||||
* @param object aListener
|
||||
* The listener object must have a method: onPageError. This method is
|
||||
* invoked with one argument, the nsIScriptError, whenever a relevant
|
||||
* page error is received.
|
||||
*/
|
||||
function PageErrorListener(aWindow, aListener)
|
||||
{
|
||||
this.window = aWindow;
|
||||
this.listener = aListener;
|
||||
}
|
||||
|
||||
PageErrorListener.prototype =
|
||||
{
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIConsoleListener]),
|
||||
|
||||
/**
|
||||
* The content window for which we listen to page errors.
|
||||
* @type nsIDOMWindow
|
||||
*/
|
||||
window: null,
|
||||
|
||||
/**
|
||||
* The listener object which is notified of page errors. It must have
|
||||
* a onPageError method which is invoked with one argument: the nsIScriptError.
|
||||
* @type object
|
||||
*/
|
||||
listener: null,
|
||||
|
||||
/**
|
||||
* Initialize the nsIConsoleService listener.
|
||||
*/
|
||||
init: function PEL_init()
|
||||
{
|
||||
Services.console.registerListener(this);
|
||||
},
|
||||
|
||||
/**
|
||||
* The nsIConsoleService observer. This method takes all the script error
|
||||
* messages belonging to the current window and sends them to the remote Web
|
||||
* Console instance.
|
||||
*
|
||||
* @param nsIScriptError aScriptError
|
||||
* The script error object coming from the nsIConsoleService.
|
||||
*/
|
||||
observe: function PEL_observe(aScriptError)
|
||||
{
|
||||
if (!this.window || !this.listener ||
|
||||
!(aScriptError instanceof Ci.nsIScriptError) ||
|
||||
!aScriptError.outerWindowID) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.isCategoryAllowed(aScriptError.category)) {
|
||||
return;
|
||||
}
|
||||
|
||||
let errorWindow =
|
||||
WebConsoleUtils.getWindowByOuterId(aScriptError.outerWindowID, this.window);
|
||||
if (!errorWindow || errorWindow.top != this.window) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.listener.onPageError(aScriptError);
|
||||
},
|
||||
|
||||
/**
|
||||
* Check if the given script error category is allowed to be tracked or not.
|
||||
* We ignore chrome-originating errors as we only care about content.
|
||||
*
|
||||
* @param string aCategory
|
||||
* The nsIScriptError category you want to check.
|
||||
* @return boolean
|
||||
* True if the category is allowed to be logged, false otherwise.
|
||||
*/
|
||||
isCategoryAllowed: function PEL_isCategoryAllowed(aCategory)
|
||||
{
|
||||
switch (aCategory) {
|
||||
case "XPConnect JavaScript":
|
||||
case "component javascript":
|
||||
case "chrome javascript":
|
||||
case "chrome registration":
|
||||
case "XBL":
|
||||
case "XBL Prototype Handler":
|
||||
case "XBL Content Sink":
|
||||
case "xbl javascript":
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
},
|
||||
|
||||
/**
|
||||
* Get the cached page errors for the current inner window.
|
||||
*
|
||||
* @return array
|
||||
* The array of cached messages. Each element is an nsIScriptError
|
||||
* with an added _type property so the remote Web Console instance can
|
||||
* tell the difference between various types of cached messages.
|
||||
*/
|
||||
getCachedMessages: function PEL_getCachedMessages()
|
||||
{
|
||||
let innerWindowId = WebConsoleUtils.getInnerWindowId(this.window);
|
||||
let result = [];
|
||||
let errors = {};
|
||||
Services.console.getMessageArray(errors, {});
|
||||
|
||||
(errors.value || []).forEach(function(aError) {
|
||||
if (!(aError instanceof Ci.nsIScriptError) ||
|
||||
aError.innerWindowID != innerWindowId ||
|
||||
!this.isCategoryAllowed(aError.category)) {
|
||||
return;
|
||||
}
|
||||
|
||||
let remoteMessage = WebConsoleUtils.cloneObject(aError);
|
||||
result.push(remoteMessage);
|
||||
}, this);
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
/**
|
||||
* Remove the nsIConsoleService listener.
|
||||
*/
|
||||
destroy: function PEL_destroy()
|
||||
{
|
||||
Services.console.unregisterListener(this);
|
||||
this.listener = this.window = null;
|
||||
},
|
||||
};
|
193
toolkit/devtools/webconsole/dbg-webconsole-actors.js
Normal file
193
toolkit/devtools/webconsole/dbg-webconsole-actors.js
Normal file
@ -0,0 +1,193 @@
|
||||
/* -*- Mode: js2; js2-basic-offset: 2; indent-tabs-mode: nil; -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* 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/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
let Cc = Components.classes;
|
||||
let Ci = Components.interfaces;
|
||||
let Cu = Components.utils;
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "Services",
|
||||
"resource://gre/modules/Services.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "PageErrorListener",
|
||||
"resource://gre/modules/devtools/WebConsoleUtils.jsm");
|
||||
|
||||
/**
|
||||
* The WebConsoleActor implements capabilities needed for the Web Console
|
||||
* feature.
|
||||
*
|
||||
* @constructor
|
||||
* @param object aConnection
|
||||
* The connection to the client, DebuggerServerConnection.
|
||||
* @param object aTabActor
|
||||
* The parent tab actor.
|
||||
*/
|
||||
function WebConsoleActor(aConnection, aTabActor)
|
||||
{
|
||||
this.conn = aConnection;
|
||||
this._browser = aTabActor.browser;
|
||||
}
|
||||
|
||||
WebConsoleActor.prototype =
|
||||
{
|
||||
/**
|
||||
* The xul:browser we work with.
|
||||
* @private
|
||||
* @type nsIDOMElement
|
||||
*/
|
||||
_browser: null,
|
||||
|
||||
/**
|
||||
* The debugger server connection instance.
|
||||
* @type object
|
||||
*/
|
||||
conn: null,
|
||||
|
||||
/**
|
||||
* The content window we work with.
|
||||
* @type nsIDOMWindow
|
||||
*/
|
||||
get window() this._browser.contentWindow,
|
||||
|
||||
/**
|
||||
* The PageErrorListener instance.
|
||||
* @type object
|
||||
*/
|
||||
pageErrorListener: null,
|
||||
|
||||
actorPrefix: "console",
|
||||
|
||||
grip: function WCA_grip()
|
||||
{
|
||||
return { actor: this.actorID };
|
||||
},
|
||||
|
||||
/**
|
||||
* Destroy the current WebConsoleActor instance.
|
||||
*/
|
||||
disconnect: function WCA_disconnect()
|
||||
{
|
||||
if (this.pageErrorListener) {
|
||||
this.pageErrorListener.destroy();
|
||||
this.pageErrorListener = null;
|
||||
}
|
||||
this.conn = this._browser = null;
|
||||
},
|
||||
|
||||
/**
|
||||
* Handler for the "startListeners" request.
|
||||
*
|
||||
* @param object aRequest
|
||||
* The JSON request object received from the Web Console client.
|
||||
* @return object
|
||||
* The response object which holds the startedListeners array.
|
||||
*/
|
||||
onStartListeners: function WCA_onStartListeners(aRequest)
|
||||
{
|
||||
let startedListeners = [];
|
||||
|
||||
while (aRequest.listeners.length > 0) {
|
||||
let listener = aRequest.listeners.shift();
|
||||
switch (listener) {
|
||||
case "PageError":
|
||||
if (!this.pageErrorListener) {
|
||||
this.pageErrorListener =
|
||||
new PageErrorListener(this.window, this);
|
||||
this.pageErrorListener.init();
|
||||
}
|
||||
startedListeners.push(listener);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return { startedListeners: startedListeners };
|
||||
},
|
||||
|
||||
/**
|
||||
* Handler for the "stopListeners" request.
|
||||
*
|
||||
* @param object aRequest
|
||||
* The JSON request object received from the Web Console client.
|
||||
* @return object
|
||||
* The response packet to send to the client: holds the
|
||||
* stoppedListeners array.
|
||||
*/
|
||||
onStopListeners: function WCA_onStopListeners(aRequest)
|
||||
{
|
||||
let stoppedListeners = [];
|
||||
|
||||
// If no specific listeners are requested to be detached, we stop all
|
||||
// listeners.
|
||||
let toDetach = aRequest.listeners || ["PageError"];
|
||||
|
||||
while (toDetach.length > 0) {
|
||||
let listener = toDetach.shift();
|
||||
switch (listener) {
|
||||
case "PageError":
|
||||
if (this.pageErrorListener) {
|
||||
this.pageErrorListener.destroy();
|
||||
this.pageErrorListener = null;
|
||||
}
|
||||
stoppedListeners.push(listener);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return { stoppedListeners: stoppedListeners };
|
||||
},
|
||||
|
||||
/**
|
||||
* Handler for page errors received from the PageErrorListener. This method
|
||||
* sends the nsIScriptError to the remote Web Console client.
|
||||
*
|
||||
* @param nsIScriptError aPageError
|
||||
* The page error we need to send to the client.
|
||||
*/
|
||||
onPageError: function WCA_onPageError(aPageError)
|
||||
{
|
||||
let packet = {
|
||||
from: this.actorID,
|
||||
type: "pageError",
|
||||
pageError: this.preparePageErrorForRemote(aPageError),
|
||||
};
|
||||
this.conn.send(packet);
|
||||
},
|
||||
|
||||
/**
|
||||
* Prepare an nsIScriptError to be sent to the client.
|
||||
*
|
||||
* @param nsIScriptError aPageError
|
||||
* The page error we need to send to the client.
|
||||
* @return object
|
||||
* The object you can send to the remote client.
|
||||
*/
|
||||
preparePageErrorForRemote: function WCA_preparePageErrorForRemote(aPageError)
|
||||
{
|
||||
return {
|
||||
message: aPageError.message,
|
||||
errorMessage: aPageError.errorMessage,
|
||||
sourceName: aPageError.sourceName,
|
||||
lineText: aPageError.sourceLine,
|
||||
lineNumber: aPageError.lineNumber,
|
||||
columnNumber: aPageError.columnNumber,
|
||||
category: aPageError.category,
|
||||
timeStamp: aPageError.timeStamp,
|
||||
warning: !!(aPageError.flags & aPageError.warningFlag),
|
||||
error: !!(aPageError.flags & aPageError.errorFlag),
|
||||
exception: !!(aPageError.flags & aPageError.exceptionFlag),
|
||||
strict: !!(aPageError.flags & aPageError.strictFlag),
|
||||
};
|
||||
},
|
||||
};
|
||||
|
||||
WebConsoleActor.prototype.requestTypes =
|
||||
{
|
||||
startListeners: WebConsoleActor.prototype.onStartListeners,
|
||||
stopListeners: WebConsoleActor.prototype.onStopListeners,
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user