Bug 583476 - WebConsole fails to activate when window.console is already defined r=sdwilsh a=betaN

This commit is contained in:
Mihai Sucan 2010-09-13 10:15:59 -07:00
parent 99059cb1d3
commit d50932e393
5 changed files with 212 additions and 116 deletions

View File

@ -1352,8 +1352,6 @@ HUD_SERVICE.prototype =
this.unregisterActiveContext(hudId);
this.unregisterDisplay(hudId);
window.wrappedJSObject.console = null;
},
/**
@ -1711,6 +1709,13 @@ HUD_SERVICE.prototype =
}
// remove the DOM Nodes
parent.removeChild(outputNode);
this.windowRegistry[aId].forEach(function(aContentWindow) {
if (aContentWindow.wrappedJSObject.console instanceof HUDConsole) {
delete aContentWindow.wrappedJSObject.console;
}
});
// remove our record of the DOM Nodes from the registry
delete this._headsUpDisplays[aId];
// remove the HeadsUpDisplay object from memory
@ -1969,8 +1974,8 @@ HUD_SERVICE.prototype =
*/
getConsoleOutputNode: function HS_getConsoleOutputNode(aId)
{
let displayNode = this.getHeadsUpDisplay(aHUDId);
return displayNode.querySelectorAll(".hud-output-node")[0];
let displayNode = this.getHeadsUpDisplay(aId);
return displayNode.querySelector(".hud-output-node");
},
/**
@ -2562,18 +2567,24 @@ HUD_SERVICE.prototype =
},
/**
* Initialize the JSTerm object to create a JS Workspace
* Initialize the JSTerm object to create a JS Workspace by attaching the UI
* into the given parent node, using the mixin.
*
* @param nsIDOMWindow aContext
* @param nsIDOMNode aParentNode
* @returns void
* @param nsIDOMWindow aContext the context used for evaluating user input
* @param nsIDOMNode aParentNode where to attach the JSTerm
* @param object aConsole
* Console object used within the JSTerm instance to report errors
* and log data (by calling console.error(), console.log(), etc).
*/
initializeJSTerm: function HS_initializeJSTerm(aContext, aParentNode)
initializeJSTerm: function HS_initializeJSTerm(aContext, aParentNode, aConsole)
{
// create Initial JS Workspace:
var context = Cu.getWeakReference(aContext);
// Attach the UI into the target parent node using the mixin.
var firefoxMixin = new JSTermFirefoxMixin(context, aParentNode);
var jsTerm = new JSTerm(context, aParentNode, firefoxMixin);
var jsTerm = new JSTerm(context, aParentNode, firefoxMixin, aConsole);
// TODO: injection of additional functionality needs re-thinking/api
// see bug 559748
},
@ -2698,47 +2709,45 @@ HUD_SERVICE.prototype =
this.registerDisplay(hudId, aContentWindow);
// check if aContentWindow has a console Object
let _console = aContentWindow.wrappedJSObject.console;
if (!_console) {
// no console exists. does the HUD exist?
let hudNode;
let childNodes = nBox.childNodes;
let hudNode;
let childNodes = nBox.childNodes;
for (var i = 0; i < childNodes.length; i++) {
let id = childNodes[i].getAttribute("id");
if (id.split("_")[0] == "hud") {
hudNode = childNodes[i];
break;
}
}
if (!hudNode) {
// get nBox object and call new HUD
let config = { parentNode: nBox,
contentWindow: aContentWindow
};
let _hud = new HeadsUpDisplay(config);
let hudWeakRef = Cu.getWeakReference(_hud);
HUDService.registerHUDWeakReference(hudWeakRef, hudId);
}
else {
// only need to attach a console object to the window object
let config = { hudNode: hudNode,
consoleOnly: true,
contentWindow: aContentWindow
};
let _hud = new HeadsUpDisplay(config);
let hudWeakRef = Cu.getWeakReference(_hud);
HUDService.registerHUDWeakReference(hudWeakRef, hudId);
aContentWindow.wrappedJSObject.console = _hud.console;
for (let i = 0; i < childNodes.length; i++) {
let id = childNodes[i].getAttribute("id");
// `id` is a string with the format "hud_<number>".
if (id.split("_")[0] == "hud") {
hudNode = childNodes[i];
break;
}
}
let hud;
// If there is no HUD for this tab create a new one.
if (!hudNode) {
// get nBox object and call new HUD
let config = { parentNode: nBox,
contentWindow: aContentWindow,
};
hud = new HeadsUpDisplay(config);
let hudWeakRef = Cu.getWeakReference(hud);
HUDService.registerHUDWeakReference(hudWeakRef, hudId);
}
else {
hud = this.hudWeakReferences[hudId].get();
hud.reattachConsole(aContentWindow.top);
}
// Check if aContentWindow has a console object. If so, don't attach
// our console, but warn the user about this.
if (aContentWindow.wrappedJSObject.console) {
this.logWarningAboutReplacedAPI(hudId);
}
else {
aContentWindow.wrappedJSObject.console = hud.console;
}
// capture JS Errors
this.setOnErrorHandler(aContentWindow);
@ -2782,23 +2791,6 @@ function HeadsUpDisplay(aConfig)
// placement: "insertBefore",
// placementChildNodeIndex: 0,
// }
//
// or, just create a new console - as there is already a HUD in place
// config: { hudNode: existingHUDDOMNode,
// consoleOnly: true,
// contentWindow: aWindow
// }
if (aConfig.consoleOnly) {
this.HUDBox = aConfig.hudNode;
this.parentNode = aConfig.hudNode.parentNode;
this.notificationBox = this.parentNode;
this.contentWindow = aConfig.contentWindow;
this.uriSpec = aConfig.contentWindow.location.href;
this.reattachConsole();
this.HUDBox.querySelectorAll(".jsterm-input-node")[0].focus();
return;
}
this.HUDBox = null;
@ -2886,11 +2878,10 @@ function HeadsUpDisplay(aConfig)
this.notificationBox.insertBefore(splitter,
this.notificationBox.childNodes[1]);
let console = this.createConsole();
this.HUDBox.lastTimestamp = 0;
this.contentWindow.wrappedJSObject.console = console;
// Create the console object that is attached to the window later.
this._console = this.createConsole();
// create the JSTerm input element
try {
@ -2946,7 +2937,7 @@ HeadsUpDisplay.prototype = {
if (appName() == "FIREFOX") {
let outputCSSClassOverride = "hud-msg-node";
let mixin = new JSTermFirefoxMixin(context, aParentNode, aExistingConsole, outputCSSClassOverride);
this.jsterm = new JSTerm(context, aParentNode, mixin);
this.jsterm = new JSTerm(context, aParentNode, mixin, this.console);
}
else {
throw new Error("Unsupported Gecko Application");
@ -2956,24 +2947,26 @@ HeadsUpDisplay.prototype = {
/**
* Re-attaches a console when the contentWindow is recreated
*
* @param nsIDOMWindow aContentWindow
* @returns void
*/
reattachConsole: function HUD_reattachConsole()
reattachConsole: function HUD_reattachConsole(aContentWindow)
{
this.hudId = this.HUDBox.getAttribute("id");
this.contentWindow = aContentWindow;
this.contentDocument = this.contentWindow.document;
this.uriSpec = this.contentWindow.location.href;
this.outputNode = this.HUDBox.querySelectorAll(".hud-output-node")[0];
if (!this._console) {
this._console = this.createConsole();
}
this.chromeWindow = HUDService.
getChromeWindowFromContentWindow(this.contentWindow);
this.chromeDocument = this.HUDBox.ownerDocument;
if (this.outputNode) {
// createConsole
this.createConsole();
if (!this.jsterm) {
this.createConsoleInput(this.contentWindow, this.consoleWrap, this.outputNode);
}
else {
throw new Error("Cannot get output node");
this.jsterm.context = Cu.getWeakReference(this.contentWindow);
this.jsterm.console = this.console;
this.jsterm.createSandbox();
}
},
@ -3260,7 +3253,13 @@ HeadsUpDisplay.prototype = {
}
},
get console() { return this._console || this.createConsole(); },
get console() {
if (!this._console) {
this._console = this.createConsole();
}
return this._console;
},
getLogCount: function HUD_getLogCount()
{
@ -3309,8 +3308,6 @@ function HUDConsole(aHeadsUpDisplay)
let outputNode = hud.outputNode;
let chromeDocument = hud.chromeDocument;
aHeadsUpDisplay._console = this;
let sendToHUDService = function console_send(aLevel, aArguments)
{
let ts = ConsoleUtils.timestamp();
@ -3790,18 +3787,18 @@ function JSTermHelper(aJSTerm)
*/
/**
* Create a JSTerminal or attach a JSTerm input node to an existing output node
*
*
* Create a JSTerminal or attach a JSTerm input node to an existing output node,
* given by the parent node.
*
* @param object aContext
* Usually nsIDOMWindow, but doesn't have to be
* @param nsIDOMNode aParentNode
* @param nsIDOMNode aParentNode where to attach the JSTerm
* @param object aMixin
* Gecko-app (or Jetpack) specific utility object
* @returns void
* @param object aConsole
* Console object to use within the JSTerm.
*/
function JSTerm(aContext, aParentNode, aMixin)
function JSTerm(aContext, aParentNode, aMixin, aConsole)
{
// set the context, attach the UI by appending to aParentNode
@ -3809,6 +3806,7 @@ function JSTerm(aContext, aParentNode, aMixin)
this.context = aContext;
this.parentNode = aParentNode;
this.mixins = aMixin;
this.console = aConsole;
this.xulElementFactory =
NodeFactory("xul", "xul", aParentNode.ownerDocument);
@ -3865,8 +3863,6 @@ JSTerm.prototype = {
createSandbox: function JST_setupSandbox()
{
// create a JS Sandbox out of this.context
this._window.wrappedJSObject.jsterm = {};
this.console = this._window.wrappedJSObject.console;
this.sandbox = new Cu.Sandbox(this._window);
this.sandbox.window = this._window;
this.sandbox.console = this.console;

View File

@ -55,6 +55,7 @@ _BROWSER_TEST_FILES = \
browser_webconsole_netlogging.js \
browser_webconsole_bug_593003_iframe_wrong_hud.js \
browser_webconsole_bug_581231_close_button.js \
browser_webconsole_consoleonpage.js \
$(NULL)
_BROWSER_TEST_PAGES = \
@ -74,6 +75,7 @@ _BROWSER_TEST_PAGES = \
test-bug-593003-iframe-wrong-hud.html \
test-bug-593003-iframe-wrong-hud-iframe.html \
test-console-replaced-api.html \
test-own-console.html \
$(NULL)
libs:: $(_BROWSER_TEST_FILES)

View File

@ -20,6 +20,7 @@
*
* Contributor(s):
* David Dahl <ddahl@mozilla.com>
* Mihai Șucan <mihai.sucan@gmail.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
@ -58,6 +59,7 @@ function testOpenWebConsole()
hud = HUDService.getHeadsUpDisplay(hudId);
HUDService.logWarningAboutReplacedAPI(hudId);
testWarning();
}
function testWarning()
@ -67,9 +69,11 @@ function testWarning()
var display = HUDService.getDisplayByURISpec(content.location.href);
var outputNode = display.querySelectorAll(".hud-output-node")[0];
executeSoon(function () {
testLogEntry(outputNode, "disabled", { success: successMsg, err: errMsg });
});
testLogEntry(outputNode, "disabled", { success: successMsg, err: errMsg });
HUDService.deactivateHUDForContext(gBrowser.selectedTab);
executeSoon(finishTest);
}
function testLogEntry(aOutputNode, aMatchString, aSuccessErrObj)
@ -77,38 +81,29 @@ function testLogEntry(aOutputNode, aMatchString, aSuccessErrObj)
var message = aOutputNode.textContent.indexOf(aMatchString);
if (message > -1) {
ok(true, aSuccessErrObj.success);
return;
return;
}
ok(false, aSuccessErrObj.err);
}
function finishTest() {
function finishTest()
{
hud = null;
hudId = null;
executeSoon(function() {
finish();
});
finish();
}
let hud, hudId, tab, browser, filterBox, outputNode;
let win = gBrowser.selectedBrowser;
let hud, hudId;
tab = gBrowser.selectedTab;
browser = gBrowser.getBrowserForTab(tab);
content.location = TEST_REPLACED_API_URI;
content.location.href = TEST_REPLACED_API_URI;
function test() {
function test()
{
waitForExplicitFinish();
browser.addEventListener("DOMContentLoaded", function onLoad(event) {
browser.removeEventListener("DOMContentLoaded", onLoad, false);
executeSoon(function (){
testOpenWebConsole();
executeSoon(function (){
testWarning();
});
});
}, false);
finishTest();
gBrowser.selectedBrowser.addEventListener("load", function() {
gBrowser.selectedBrowser.removeEventListener("load", arguments.callee,
true);
testOpenWebConsole();
}, true);
}

View File

@ -0,0 +1,81 @@
/* vim:set ts=2 sw=2 sts=2 et: */
/* ***** BEGIN LICENSE BLOCK *****
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*
* Contributor(s):
* Julian Viereck <jviereck@mozilla.com>
* Mihai Șucan <mihai.sucan@gmail.com>
*
* ***** END LICENSE BLOCK ***** */
const Cu = Components.utils;
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/HUDService.jsm");
let hud;
let hudId;
function testOpenWebConsole()
{
HUDService.activateHUDForContext(gBrowser.selectedTab);
is(HUDService.displaysIndex().length, 1, "WebConsole was opened");
hudId = HUDService.displaysIndex()[0];
hud = HUDService.hudWeakReferences[hudId].get();
testOwnConsole();
}
function testConsoleOnPage() {
let console = content.wrappedJSObject.console;
isnot(console, undefined, "Console object defined on page");
is(console.foo, "bar", "Custom console is not overwritten");
}
function testOwnConsole()
{
// Test console on the page. There is already one so it shouldn't be
// overwritten by the WebConsole's console.
testConsoleOnPage();
// Check that the console object is set on the jsterm object although there
// is no console object added to the page.
ok(hud.jsterm.console, "JSTerm console is defined");
ok(hud.jsterm.console === hud._console, "JSTerm console is same as HUD console");
content.wrappedJSObject.loadIFrame(function(iFrame) {
// Test the console in the iFrame.
let consoleIFrame = iFrame.wrappedJSObject.contentWindow.console;
isnot(consoleIFrame, undefined, "Console object defined in iFrame");
ok(consoleIFrame === hud._console, "Console on the page is hud console");
// Close the hud and see which console is still around.
HUDService.deactivateHUDForContext(gBrowser.selectedTab);
executeSoon(function () {
consoleIFrame = iFrame.wrappedJSObject.contentWindow.console;
is(consoleIFrame, undefined, "Console object was removed from iFrame");
testConsoleOnPage();
hud = hudId = null;
gBrowser.removeCurrentTab();
finish();
});
});
}
function test()
{
waitForExplicitFinish();
gBrowser.selectedTab = gBrowser.addTab();
gBrowser.selectedBrowser.addEventListener("load", function() {
gBrowser.selectedBrowser.removeEventListener("load", arguments.callee, true);
waitForFocus(testOpenWebConsole, content);
}, true);
content.location =
"http://example.com/browser/toolkit/components/console/hudservice/tests/browser/test-own-console.html";
}

View File

@ -0,0 +1,22 @@
<!DOCTYPE HTML>
<html dir="ltr" xml:lang="en-US" lang="en-US">
<head>
<script>
window.console = {
foo: "bar"
}
function loadIFrame(aCallback) {
var iframe = document.body.querySelector("iframe");
iframe.addEventListener("load", function() {
iframe.removeEventListener("load", arguments.callee, true);
aCallback(iframe);
}, true);
iframe.setAttribute("src", "test-console.html");
}
</script>
</head>
<body>
<iframe></iframe>
</body>