mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
merge m-c to fx-team
This commit is contained in:
commit
fe9e4d5202
@ -1,6 +1,7 @@
|
||||
browser.jar:
|
||||
* content/browser/inspector.html (highlighter/inspector.html)
|
||||
content/browser/NetworkPanel.xhtml (webconsole/NetworkPanel.xhtml)
|
||||
content/browser/devtools/HUDService-content.js (webconsole/HUDService-content.js)
|
||||
* content/browser/scratchpad.xul (scratchpad/scratchpad.xul)
|
||||
content/browser/scratchpad.js (scratchpad/scratchpad.js)
|
||||
content/browser/splitview.css (shared/splitview.css)
|
||||
|
790
browser/devtools/webconsole/HUDService-content.js
Normal file
790
browser/devtools/webconsole/HUDService-content.js
Normal file
@ -0,0 +1,790 @@
|
||||
/* -*- Mode: js2; js2-basic-offset: 2; indent-tabs-mode: nil; -*- */
|
||||
/* vim: set ft=javascript 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";
|
||||
|
||||
// This code is appended to the browser content script.
|
||||
(function _HUDServiceContent() {
|
||||
let Cc = Components.classes;
|
||||
let Ci = Components.interfaces;
|
||||
let Cu = Components.utils;
|
||||
|
||||
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);
|
||||
|
||||
let XPCOMUtils = tempScope.XPCOMUtils;
|
||||
let Services = tempScope.Services;
|
||||
let gConsoleStorage = tempScope.ConsoleAPIStorage;
|
||||
let WebConsoleUtils = tempScope.WebConsoleUtils;
|
||||
let l10n = WebConsoleUtils.l10n;
|
||||
tempScope = null;
|
||||
|
||||
let _alive = true; // Track if this content script should still be alive.
|
||||
|
||||
/**
|
||||
* The Web Console content instance manager.
|
||||
*/
|
||||
let Manager = {
|
||||
get window() content,
|
||||
get console() this.window.console,
|
||||
sandbox: null,
|
||||
hudId: null,
|
||||
_sequence: 0,
|
||||
_messageListeners: ["WebConsole:Init", "WebConsole:EnableFeature",
|
||||
"WebConsole:DisableFeature", "WebConsole:Destroy"],
|
||||
_messageHandlers: null,
|
||||
_enabledFeatures: null,
|
||||
|
||||
/**
|
||||
* Getter for a unique ID for the current Web Console content instance.
|
||||
*/
|
||||
get sequenceId() "HUDContent-" + (++this._sequence),
|
||||
|
||||
/**
|
||||
* Initialize the Web Console manager.
|
||||
*/
|
||||
init: function Manager_init()
|
||||
{
|
||||
this._enabledFeatures = [];
|
||||
this._messageHandlers = {};
|
||||
|
||||
this._messageListeners.forEach(function(aName) {
|
||||
addMessageListener(aName, this);
|
||||
}, this);
|
||||
|
||||
// Need to track the owner XUL window to listen to the unload and TabClose
|
||||
// events, to avoid memory leaks.
|
||||
let xulWindow = this.window.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIWebNavigation)
|
||||
.QueryInterface(Ci.nsIDocShell)
|
||||
.chromeEventHandler.ownerDocument.defaultView;
|
||||
|
||||
xulWindow.addEventListener("unload", this._onXULWindowClose, false);
|
||||
|
||||
let tabContainer = xulWindow.gBrowser.tabContainer;
|
||||
tabContainer.addEventListener("TabClose", this._onTabClose, false);
|
||||
|
||||
// Need to track private browsing change and quit application notifications,
|
||||
// again to avoid memory leaks. The Web Console main process cannot notify
|
||||
// this content script when the XUL window close, tab close, private
|
||||
// browsing change and quit application events happen, so we must call
|
||||
// Manager.destroy() on our own.
|
||||
Services.obs.addObserver(this, "private-browsing-change-granted", false);
|
||||
Services.obs.addObserver(this, "quit-application-granted", false);
|
||||
},
|
||||
|
||||
/**
|
||||
* The message handler. This method forwards all the remote messages to the
|
||||
* appropriate code.
|
||||
*/
|
||||
receiveMessage: function Manager_receiveMessage(aMessage)
|
||||
{
|
||||
if (!_alive) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!aMessage.json || (aMessage.name != "WebConsole:Init" &&
|
||||
aMessage.json.hudId != this.hudId)) {
|
||||
Cu.reportError("Web Console content script: received message " +
|
||||
aMessage.name + " from wrong hudId!");
|
||||
return;
|
||||
}
|
||||
|
||||
switch (aMessage.name) {
|
||||
case "WebConsole:Init":
|
||||
this._onInit(aMessage.json);
|
||||
break;
|
||||
case "WebConsole:EnableFeature":
|
||||
this.enableFeature(aMessage.json.feature, aMessage.json);
|
||||
break;
|
||||
case "WebConsole:DisableFeature":
|
||||
this.disableFeature(aMessage.json.feature);
|
||||
break;
|
||||
case "WebConsole:Destroy":
|
||||
this.destroy();
|
||||
break;
|
||||
default: {
|
||||
let handler = this._messageHandlers[aMessage.name];
|
||||
handler && handler(aMessage.json);
|
||||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Observe notifications from the nsIObserverService.
|
||||
*
|
||||
* @param mixed aSubject
|
||||
* @param string aTopic
|
||||
* @param mixed aData
|
||||
*/
|
||||
observe: function Manager_observe(aSubject, aTopic, aData)
|
||||
{
|
||||
if (_alive && (aTopic == "quit-application-granted" ||
|
||||
(aTopic == "private-browsing-change-granted" &&
|
||||
(aData == "enter" || aData == "exit")))) {
|
||||
this.destroy();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* The manager initialization code. This method is called when the Web Console
|
||||
* remote process initializes the content process (this code!).
|
||||
*
|
||||
* @param object aMessage
|
||||
* The object received from the remote process. The WebConsole:Init
|
||||
* message properties:
|
||||
* - hudId - (required) the remote Web Console instance ID.
|
||||
* - features - (optional) array of features you want to enable from
|
||||
* the start. For each feature you enable you can pass feature-specific
|
||||
* options in a property on the JSON object you send with the same name
|
||||
* as the feature. See this.enableFeature() for the list of available
|
||||
* features.
|
||||
* - cachedMessages - (optional) an array of cached messages you want
|
||||
* to receive. See this._sendCachedMessages() for the list of available
|
||||
* message types.
|
||||
*
|
||||
* Example message:
|
||||
* {
|
||||
* hudId: "foo1",
|
||||
* features: ["JSTerm", "ConsoleAPI"],
|
||||
* ConsoleAPI: { ... }, // ConsoleAPI-specific options
|
||||
* cachedMessages: ["ConsoleAPI"],
|
||||
* }
|
||||
*/
|
||||
_onInit: function Manager_onInit(aMessage)
|
||||
{
|
||||
this.hudId = aMessage.hudId;
|
||||
if (aMessage.features) {
|
||||
aMessage.features.forEach(function(aFeature) {
|
||||
this.enableFeature(aFeature, aMessage[aFeature]);
|
||||
}, this);
|
||||
}
|
||||
|
||||
if (aMessage.cachedMessages) {
|
||||
this._sendCachedMessages(aMessage.cachedMessages);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Add a remote message handler. This is used by other components of the Web
|
||||
* Console content script.
|
||||
*
|
||||
* @param string aName
|
||||
* Message name to listen for.
|
||||
* @param function aCallback
|
||||
* Function to execute when the message is received. This function is
|
||||
* given the JSON object that came from the remote Web Console
|
||||
* instance.
|
||||
* Only one callback per message name is allowed!
|
||||
*/
|
||||
addMessageHandler: function Manager_addMessageHandler(aName, aCallback)
|
||||
{
|
||||
if (aName in this._messageHandlers) {
|
||||
Cu.reportError("Web Console content script: addMessageHandler() called for an existing message handler: " + aName);
|
||||
return;
|
||||
}
|
||||
|
||||
this._messageHandlers[aName] = aCallback;
|
||||
addMessageListener(aName, this);
|
||||
},
|
||||
|
||||
/**
|
||||
* Remove the message handler for the given name.
|
||||
*
|
||||
* @param string aName
|
||||
* Message name for the handler you want removed.
|
||||
*/
|
||||
removeMessageHandler: function Manager_removeMessageHandler(aName)
|
||||
{
|
||||
if (!(aName in this._messageHandlers)) {
|
||||
return;
|
||||
}
|
||||
|
||||
delete this._messageHandlers[aName];
|
||||
removeMessageListener(aName, this);
|
||||
},
|
||||
|
||||
/**
|
||||
* Send a message to the remote Web Console instance.
|
||||
*
|
||||
* @param string aName
|
||||
* The name of the message you want to send.
|
||||
* @param object aMessage
|
||||
* The message object you want to send.
|
||||
*/
|
||||
sendMessage: function Manager_sendMessage(aName, aMessage)
|
||||
{
|
||||
aMessage.hudId = this.hudId;
|
||||
if (!("id" in aMessage)) {
|
||||
aMessage.id = this.sequenceId;
|
||||
}
|
||||
|
||||
sendAsyncMessage(aName, aMessage);
|
||||
},
|
||||
|
||||
/**
|
||||
* Enable a feature in the Web Console content script. A feature is generally
|
||||
* a set of observers/listeners that are added in the content process. This
|
||||
* content script exposes the data via the message manager for the features
|
||||
* you enable.
|
||||
*
|
||||
* Supported features:
|
||||
* - JSTerm - a JavaScript "terminal" which allows code execution.
|
||||
* - ConsoleAPI - support for routing the window.console API to the remote
|
||||
* process.
|
||||
* - PageError - route all the nsIScriptErrors from the nsIConsoleService
|
||||
* to the remote process.
|
||||
*
|
||||
* @param string aFeature
|
||||
* One of the supported features: JSTerm, ConsoleAPI.
|
||||
* @param object [aMessage]
|
||||
* Optional JSON message object coming from the remote Web Console
|
||||
* instance. This can be used for feature-specific options.
|
||||
*/
|
||||
enableFeature: function Manager_enableFeature(aFeature, aMessage)
|
||||
{
|
||||
if (this._enabledFeatures.indexOf(aFeature) != -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (aFeature) {
|
||||
case "JSTerm":
|
||||
JSTerm.init(aMessage);
|
||||
break;
|
||||
case "ConsoleAPI":
|
||||
ConsoleAPIObserver.init(aMessage);
|
||||
break;
|
||||
case "PageError":
|
||||
ConsoleListener.init(aMessage);
|
||||
break;
|
||||
default:
|
||||
Cu.reportError("Web Console content: unknown feature " + aFeature);
|
||||
break;
|
||||
}
|
||||
|
||||
this._enabledFeatures.push(aFeature);
|
||||
},
|
||||
|
||||
/**
|
||||
* Disable a Web Console content script feature.
|
||||
*
|
||||
* @see this.enableFeature
|
||||
* @param string aFeature
|
||||
* One of the supported features - see this.enableFeature() for the
|
||||
* list of supported features.
|
||||
*/
|
||||
disableFeature: function Manager_disableFeature(aFeature)
|
||||
{
|
||||
let index = this._enabledFeatures.indexOf(aFeature);
|
||||
if (index == -1) {
|
||||
return;
|
||||
}
|
||||
this._enabledFeatures.splice(index, 1);
|
||||
|
||||
switch (aFeature) {
|
||||
case "JSTerm":
|
||||
JSTerm.destroy();
|
||||
break;
|
||||
case "ConsoleAPI":
|
||||
ConsoleAPIObserver.destroy();
|
||||
break;
|
||||
case "PageError":
|
||||
ConsoleListener.destroy();
|
||||
break;
|
||||
default:
|
||||
Cu.reportError("Web Console content: unknown feature " + aFeature);
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Send the cached messages to the remote Web Console instance.
|
||||
*
|
||||
* @private
|
||||
* @param array aMessageTypes
|
||||
* An array that lists which kinds of messages you want. Supported
|
||||
* message types: "ConsoleAPI" and "PageError".
|
||||
*/
|
||||
_sendCachedMessages: function Manager__sendCachedMessages(aMessageTypes)
|
||||
{
|
||||
let messages = [];
|
||||
|
||||
while (aMessageTypes.length > 0) {
|
||||
switch (aMessageTypes.shift()) {
|
||||
case "ConsoleAPI":
|
||||
messages.push.apply(messages, ConsoleAPIObserver.getCachedMessages());
|
||||
break;
|
||||
case "PageError":
|
||||
messages.push.apply(messages, ConsoleListener.getCachedMessages());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
messages.sort(function(a, b) { return a.timeStamp - b.timeStamp; });
|
||||
|
||||
this.sendMessage("WebConsole:CachedMessages", {messages: messages});
|
||||
},
|
||||
|
||||
/**
|
||||
* The XUL window "unload" event handler which destroys this content script
|
||||
* instance.
|
||||
* @private
|
||||
*/
|
||||
_onXULWindowClose: function Manager__onXULWindowClose()
|
||||
{
|
||||
if (_alive) {
|
||||
Manager.destroy();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* The "TabClose" event handler which destroys this content script
|
||||
* instance, if needed.
|
||||
* @private
|
||||
*/
|
||||
_onTabClose: function Manager__onTabClose(aEvent)
|
||||
{
|
||||
let tab = aEvent.target;
|
||||
if (_alive && tab.linkedBrowser.contentWindow === Manager.window) {
|
||||
Manager.destroy();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Destroy the Web Console content script instance.
|
||||
*/
|
||||
destroy: function Manager_destroy()
|
||||
{
|
||||
Services.obs.removeObserver(this, "private-browsing-change-granted");
|
||||
Services.obs.removeObserver(this, "quit-application-granted");
|
||||
|
||||
_alive = false;
|
||||
let xulWindow = this.window.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIWebNavigation)
|
||||
.QueryInterface(Ci.nsIDocShell)
|
||||
.chromeEventHandler.ownerDocument.defaultView;
|
||||
|
||||
xulWindow.removeEventListener("unload", this._onXULWindowClose, false);
|
||||
let tabContainer = xulWindow.gBrowser.tabContainer;
|
||||
tabContainer.removeEventListener("TabClose", this._onTabClose, false);
|
||||
|
||||
this._messageListeners.forEach(function(aName) {
|
||||
removeMessageListener(aName, this);
|
||||
}, this);
|
||||
|
||||
this._enabledFeatures.slice().forEach(this.disableFeature, this);
|
||||
|
||||
this.hudId = null;
|
||||
this._messageHandlers = null;
|
||||
Manager = ConsoleAPIObserver = JSTerm = ConsoleListener = null;
|
||||
Cc = Ci = Cu = XPCOMUtils = Services = gConsoleStorage =
|
||||
WebConsoleUtils = l10n = null;
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* The JavaScript terminal is meant to allow remote code execution for the Web
|
||||
* Console.
|
||||
*/
|
||||
let JSTerm = {
|
||||
/**
|
||||
* Evaluation result objects are cached in this object. The chrome process can
|
||||
* request any object based on its ID.
|
||||
*/
|
||||
_objectCache: null,
|
||||
|
||||
/**
|
||||
* Initialize the JavaScript terminal feature.
|
||||
*/
|
||||
init: function JST_init()
|
||||
{
|
||||
this._objectCache = {};
|
||||
|
||||
Manager.addMessageHandler("JSTerm:GetEvalObject",
|
||||
this.handleGetEvalObject.bind(this));
|
||||
Manager.addMessageHandler("JSTerm:ClearObjectCache",
|
||||
this.handleClearObjectCache.bind(this));
|
||||
},
|
||||
|
||||
/**
|
||||
* Handler for the remote "JSTerm:GetEvalObject" message. This allows the
|
||||
* remote Web Console instance to retrieve an object from the content process.
|
||||
*
|
||||
* @param object aRequest
|
||||
* The message that requests the content object. Properties: cacheId,
|
||||
* objectId and resultCacheId.
|
||||
*
|
||||
* Evaluated objects are stored in "buckets" (cache IDs). Each object
|
||||
* is assigned an ID (object ID). You can request a specific object
|
||||
* (objectId) from a specific cache (cacheId) and tell where the result
|
||||
* should be cached (resultCacheId). The requested object can have
|
||||
* further references to other objects - those references will be
|
||||
* cached in the "bucket" of your choice (based on resultCacheId). If
|
||||
* you do not provide any resultCacheId in the request message, then
|
||||
* cacheId will be used.
|
||||
*/
|
||||
handleGetEvalObject: function JST_handleGetEvalObject(aRequest)
|
||||
{
|
||||
if (aRequest.cacheId in this._objectCache &&
|
||||
aRequest.objectId in this._objectCache[aRequest.cacheId]) {
|
||||
let object = this._objectCache[aRequest.cacheId][aRequest.objectId];
|
||||
let resultCacheId = aRequest.resultCacheId || aRequest.cacheId;
|
||||
let message = {
|
||||
id: aRequest.id,
|
||||
cacheId: aRequest.cacheId,
|
||||
objectId: aRequest.objectId,
|
||||
object: this.prepareObjectForRemote(object, resultCacheId),
|
||||
childrenCacheId: resultCacheId,
|
||||
};
|
||||
Manager.sendMessage("JSTerm:EvalObject", message);
|
||||
}
|
||||
else {
|
||||
Cu.reportError("JSTerm:GetEvalObject request " + aRequest.id +
|
||||
": stale object.");
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Handler for the remote "JSTerm:ClearObjectCache" message. This allows the
|
||||
* remote Web Console instance to clear the cache of objects that it no longer
|
||||
* uses.
|
||||
*
|
||||
* @param object aRequest
|
||||
* An object that holds one property: the cacheId you want cleared.
|
||||
*/
|
||||
handleClearObjectCache: function JST_handleClearObjectCache(aRequest)
|
||||
{
|
||||
if (aRequest.cacheId in this._objectCache) {
|
||||
delete this._objectCache[aRequest.cacheId];
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Prepare an object to be sent to the remote Web Console instance.
|
||||
*
|
||||
* @param object aObject
|
||||
* The object you want to send to the remote Web Console instance.
|
||||
* @param number aCacheId
|
||||
* Cache ID where you want object references to be stored into. The
|
||||
* given object may include references to other objects - those
|
||||
* references will be stored in the given cache ID so the remote
|
||||
* process can later retrieve them as well.
|
||||
* @return array
|
||||
* An array that holds one element for each enumerable property and
|
||||
* method in aObject. Each element describes the property. For details
|
||||
* see WebConsoleUtils.namesAndValuesOf().
|
||||
*/
|
||||
prepareObjectForRemote:
|
||||
function JST_prepareObjectForRemote(aObject, aCacheId)
|
||||
{
|
||||
// Cache the properties that have inspectable values.
|
||||
let propCache = this._objectCache[aCacheId] || {};
|
||||
let result = WebConsoleUtils.namesAndValuesOf(aObject, propCache);
|
||||
if (!(aCacheId in this._objectCache) && Object.keys(propCache).length > 0) {
|
||||
this._objectCache[aCacheId] = propCache;
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
/**
|
||||
* Destroy the JSTerm instance.
|
||||
*/
|
||||
destroy: function JST_destroy()
|
||||
{
|
||||
Manager.removeMessageHandler("JSTerm:GetEvalObject");
|
||||
Manager.removeMessageHandler("JSTerm:ClearObjectCache");
|
||||
|
||||
delete this._objectCache;
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* The window.console API observer. This allows the window.console API messages
|
||||
* to be sent to the remote Web Console instance.
|
||||
*/
|
||||
let ConsoleAPIObserver = {
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver]),
|
||||
|
||||
/**
|
||||
* Initialize the window.console API observer.
|
||||
*/
|
||||
init: function CAO_init()
|
||||
{
|
||||
// Note that the observer is process-wide. We will filter the messages as
|
||||
// needed, see CAO_observe().
|
||||
Services.obs.addObserver(this, "console-api-log-event", false);
|
||||
|
||||
Manager.addMessageHandler("ConsoleAPI:ClearCache",
|
||||
this.handleClearCache.bind(this));
|
||||
},
|
||||
|
||||
/**
|
||||
* The console API message observer. When messages are received from the
|
||||
* observer service we forward them to the remote Web Console instance.
|
||||
*
|
||||
* @param object aMessage
|
||||
* The message object receives from the observer service.
|
||||
* @param string aTopic
|
||||
* The message topic received from the observer service.
|
||||
*/
|
||||
observe: function CAO_observe(aMessage, aTopic)
|
||||
{
|
||||
if (!_alive || !aMessage || aTopic != "console-api-log-event") {
|
||||
return;
|
||||
}
|
||||
|
||||
let apiMessage = aMessage.wrappedJSObject;
|
||||
|
||||
let msgWindow =
|
||||
WebConsoleUtils.getWindowByOuterId(apiMessage.ID, Manager.window);
|
||||
if (!msgWindow || msgWindow.top != Manager.window) {
|
||||
// Not the same window!
|
||||
return;
|
||||
}
|
||||
|
||||
let messageToChrome = {};
|
||||
this._prepareApiMessageForRemote(apiMessage, messageToChrome);
|
||||
Manager.sendMessage("WebConsole:ConsoleAPI", messageToChrome);
|
||||
},
|
||||
|
||||
/**
|
||||
* Prepare a message from the console APi to be sent to the remote Web Console
|
||||
* instance.
|
||||
*
|
||||
* @param object aOriginalMessage
|
||||
* The original message received from console-api-log-event.
|
||||
* @param object aRemoteMessage
|
||||
* The object you want to send to the remote Web Console. This object
|
||||
* is updated to hold information from the original message. New
|
||||
* properties added:
|
||||
* - timeStamp
|
||||
* Message timestamp (same as the aOriginalMessage.timeStamp property).
|
||||
* - apiMessage
|
||||
* An object that copies almost all the properties from
|
||||
* aOriginalMessage. Arguments might be skipped if it holds references
|
||||
* to objects that cannot be sent as they are to the remote Web Console
|
||||
* instance.
|
||||
* - argumentsToString
|
||||
* Optional: the aOriginalMessage.arguments object stringified.
|
||||
*
|
||||
* The apiMessage.arguments property is set to hold data appropriate
|
||||
* to the message level. A similar approach is used for
|
||||
* argumentsToString.
|
||||
*/
|
||||
_prepareApiMessageForRemote:
|
||||
function CAO__prepareApiMessageForRemote(aOriginalMessage, aRemoteMessage)
|
||||
{
|
||||
aRemoteMessage.apiMessage =
|
||||
WebConsoleUtils.cloneObject(aOriginalMessage, true,
|
||||
function(aKey, aValue, aObject) {
|
||||
// We need to skip the arguments property from the original object.
|
||||
if (aKey == "wrappedJSObject" || aObject === aOriginalMessage &&
|
||||
aKey == "arguments") {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
aRemoteMessage.timeStamp = aOriginalMessage.timeStamp;
|
||||
|
||||
switch (aOriginalMessage.level) {
|
||||
case "trace":
|
||||
case "time":
|
||||
case "timeEnd":
|
||||
case "group":
|
||||
case "groupCollapsed":
|
||||
aRemoteMessage.apiMessage.arguments =
|
||||
WebConsoleUtils.cloneObject(aOriginalMessage.arguments, true);
|
||||
break;
|
||||
|
||||
case "log":
|
||||
case "info":
|
||||
case "warn":
|
||||
case "error":
|
||||
case "debug":
|
||||
case "groupEnd":
|
||||
aRemoteMessage.argumentsToString =
|
||||
Array.map(aOriginalMessage.arguments || [],
|
||||
this._formatObject.bind(this));
|
||||
break;
|
||||
|
||||
case "dir": {
|
||||
aRemoteMessage.objectsCacheId = Manager.sequenceId;
|
||||
aRemoteMessage.argumentsToString = [];
|
||||
let mapFunction = function(aItem) {
|
||||
aRemoteMessage.argumentsToString.push(this._formatObject(aItem));
|
||||
if (WebConsoleUtils.isObjectInspectable(aItem)) {
|
||||
return JSTerm.prepareObjectForRemote(aItem,
|
||||
aRemoteMessage.objectsCacheId);
|
||||
}
|
||||
return aItem;
|
||||
}.bind(this);
|
||||
|
||||
aRemoteMessage.apiMessage.arguments =
|
||||
Array.map(aOriginalMessage.arguments || [], mapFunction);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
Cu.reportError("Unknown Console API log level: " +
|
||||
aOriginalMessage.level);
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Format an object's value to be displayed in the Web Console.
|
||||
*
|
||||
* @private
|
||||
* @param object aObject
|
||||
* The object you want to display.
|
||||
* @return string
|
||||
* The string you can display for the given object.
|
||||
*/
|
||||
_formatObject: function CAO__formatObject(aObject)
|
||||
{
|
||||
return typeof aObject == "string" ?
|
||||
aObject : WebConsoleUtils.formatResult(aObject);
|
||||
},
|
||||
|
||||
/**
|
||||
* Get the cached messages for the current inner window.
|
||||
*
|
||||
* @see this._prepareApiMessageForRemote()
|
||||
* @return array
|
||||
* The array of cached messages. Each element is a Console API
|
||||
* prepared to be sent to the remote Web Console instance.
|
||||
*/
|
||||
getCachedMessages: function CAO_getCachedMessages()
|
||||
{
|
||||
let innerWindowId = WebConsoleUtils.getInnerWindowId(Manager.window);
|
||||
let messages = gConsoleStorage.getEvents(innerWindowId);
|
||||
|
||||
let result = messages.map(function(aMessage) {
|
||||
let remoteMessage = { _type: "ConsoleAPI" };
|
||||
this._prepareApiMessageForRemote(aMessage.wrappedJSObject, remoteMessage);
|
||||
return remoteMessage;
|
||||
}, this);
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
/**
|
||||
* Handler for the "ConsoleAPI:ClearCache" message.
|
||||
*/
|
||||
handleClearCache: function CAO_handleClearCache()
|
||||
{
|
||||
let windowId = WebConsoleUtils.getInnerWindowId(Manager.window);
|
||||
gConsoleStorage.clearEvents(windowId);
|
||||
},
|
||||
|
||||
/**
|
||||
* Destroy the ConsoleAPIObserver listeners.
|
||||
*/
|
||||
destroy: function CAO_destroy()
|
||||
{
|
||||
Manager.removeMessageHandler("ConsoleAPI:ClearCache");
|
||||
Services.obs.removeObserver(this, "console-api-log-event");
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* The nsIConsoleService listener. This is used to send all the page errors
|
||||
* (JavaScript, CSS and more) to the remote Web Console instance.
|
||||
*/
|
||||
let ConsoleListener = {
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIConsoleListener]),
|
||||
|
||||
/**
|
||||
* Initialize the nsIConsoleService listener.
|
||||
*/
|
||||
init: function CL_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 CL_observe(aScriptError)
|
||||
{
|
||||
if (!_alive || !(aScriptError instanceof Ci.nsIScriptError) ||
|
||||
!aScriptError.outerWindowID) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (aScriptError.category) {
|
||||
// We ignore chrome-originating errors as we only care about content.
|
||||
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;
|
||||
}
|
||||
|
||||
let errorWindow =
|
||||
WebConsoleUtils.getWindowByOuterId(aScriptError.outerWindowID,
|
||||
Manager.window);
|
||||
if (!errorWindow || errorWindow.top != Manager.window) {
|
||||
return;
|
||||
}
|
||||
|
||||
Manager.sendMessage("WebConsole:PageError", { pageError: aScriptError });
|
||||
},
|
||||
|
||||
/**
|
||||
* 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 CL_getCachedMessages()
|
||||
{
|
||||
let innerWindowId = WebConsoleUtils.getInnerWindowId(Manager.window);
|
||||
let result = [];
|
||||
let errors = {};
|
||||
Services.console.getMessageArray(errors, {});
|
||||
|
||||
(errors.value || []).forEach(function(aError) {
|
||||
if (!(aError instanceof Ci.nsIScriptError) ||
|
||||
aError.innerWindowID != innerWindowId) {
|
||||
return;
|
||||
}
|
||||
|
||||
let remoteMessage = WebConsoleUtils.cloneObject(aError);
|
||||
remoteMessage._type = "PageError";
|
||||
result.push(remoteMessage);
|
||||
});
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
/**
|
||||
* Remove the nsIConsoleService listener.
|
||||
*/
|
||||
destroy: function CL_destroy()
|
||||
{
|
||||
Services.console.unregisterListener(this);
|
||||
},
|
||||
};
|
||||
|
||||
Manager.init();
|
||||
})();
|
File diff suppressed because it is too large
Load Diff
@ -46,8 +46,10 @@ include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
EXTRA_JS_MODULES = \
|
||||
PropertyPanel.jsm \
|
||||
PropertyPanelAsync.jsm \
|
||||
NetworkHelper.jsm \
|
||||
AutocompletePopup.jsm \
|
||||
WebConsoleUtils.jsm \
|
||||
gcli.jsm \
|
||||
GcliCommands.jsm \
|
||||
GcliTiltCommands.jsm \
|
||||
|
466
browser/devtools/webconsole/PropertyPanelAsync.jsm
Normal file
466
browser/devtools/webconsole/PropertyPanelAsync.jsm
Normal file
@ -0,0 +1,466 @@
|
||||
/* -*- Mode: js2; js2-basic-offset: 2; indent-tabs-mode: nil; -*- */
|
||||
/* vim: set ft=javascript 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;
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "WebConsoleUtils", function () {
|
||||
let obj = {};
|
||||
Cu.import("resource:///modules/WebConsoleUtils.jsm", obj);
|
||||
return obj.WebConsoleUtils;
|
||||
});
|
||||
|
||||
var EXPORTED_SYMBOLS = ["PropertyPanel", "PropertyTreeView"];
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//// PropertyTreeView.
|
||||
|
||||
/**
|
||||
* This is an implementation of the nsITreeView interface. For comments on the
|
||||
* interface properties, see the documentation:
|
||||
* https://developer.mozilla.org/en/XPCOM_Interface_Reference/nsITreeView
|
||||
*/
|
||||
var PropertyTreeView = function() {
|
||||
this._rows = [];
|
||||
this._objectCache = {};
|
||||
};
|
||||
|
||||
PropertyTreeView.prototype = {
|
||||
/**
|
||||
* Stores the visible rows of the tree.
|
||||
* @private
|
||||
*/
|
||||
_rows: null,
|
||||
|
||||
/**
|
||||
* Stores the nsITreeBoxObject for this tree.
|
||||
* @private
|
||||
*/
|
||||
_treeBox: null,
|
||||
|
||||
/**
|
||||
* Stores cached information about local objects being inspected.
|
||||
* @private
|
||||
*/
|
||||
_objectCache: null,
|
||||
|
||||
/**
|
||||
* Use this setter to update the content of the tree.
|
||||
*
|
||||
* @param object aObject
|
||||
* An object that holds information about the object you want to
|
||||
* display in the property panel. Object properties:
|
||||
* - object:
|
||||
* This is the raw object you want to display. You can only provide
|
||||
* this object if you want the property panel to work in sync mode.
|
||||
* - remoteObject:
|
||||
* An array that holds information on the remote object being
|
||||
* inspected. Each element in this array describes each property in the
|
||||
* remote object. See WebConsoleUtils.namesAndValuesOf() for details.
|
||||
* - rootCacheId:
|
||||
* The cache ID where the objects referenced in remoteObject are found.
|
||||
* - panelCacheId:
|
||||
* The cache ID where any object retrieved by this property panel
|
||||
* instance should be stored into.
|
||||
* - remoteObjectProvider:
|
||||
* A function that is invoked when a new object is needed. This is
|
||||
* called when the user tries to expand an inspectable property. The
|
||||
* callback must take four arguments:
|
||||
* - fromCacheId:
|
||||
* Tells from where to retrieve the object the user picked (from
|
||||
* which cache ID).
|
||||
* - objectId:
|
||||
* The object ID the user wants.
|
||||
* - panelCacheId:
|
||||
* Tells in which cache ID to store the objects referenced by
|
||||
* objectId so they can be retrieved later.
|
||||
* - callback:
|
||||
* The callback function to be invoked when the remote object is
|
||||
* received. This function takes one argument: the raw message
|
||||
* received from the Web Console content script.
|
||||
*/
|
||||
set data(aData) {
|
||||
let oldLen = this._rows.length;
|
||||
|
||||
this._cleanup();
|
||||
|
||||
if (!aData) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (aData.remoteObject) {
|
||||
this._rootCacheId = aData.rootCacheId;
|
||||
this._panelCacheId = aData.panelCacheId;
|
||||
this._remoteObjectProvider = aData.remoteObjectProvider;
|
||||
this._rows = [].concat(aData.remoteObject);
|
||||
this._updateRemoteObject(this._rows, 0);
|
||||
}
|
||||
else if (aData.object) {
|
||||
this._rows = this._inspectObject(aData.object);
|
||||
}
|
||||
else {
|
||||
throw new Error("First argument must have a .remoteObject or " +
|
||||
"an .object property!");
|
||||
}
|
||||
|
||||
if (this._treeBox) {
|
||||
this._treeBox.beginUpdateBatch();
|
||||
if (oldLen) {
|
||||
this._treeBox.rowCountChanged(0, -oldLen);
|
||||
}
|
||||
this._treeBox.rowCountChanged(0, this._rows.length);
|
||||
this._treeBox.endUpdateBatch();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Update a remote object so it can be used with the tree view. This method
|
||||
* adds properties to each array element.
|
||||
*
|
||||
* @private
|
||||
* @param array aObject
|
||||
* The remote object you want prepared for use with the tree view.
|
||||
* @param number aLevel
|
||||
* The level you want to give to each property in the remote object.
|
||||
*/
|
||||
_updateRemoteObject: function PTV__updateRemoteObject(aObject, aLevel)
|
||||
{
|
||||
aObject.forEach(function(aElement) {
|
||||
aElement.level = aLevel;
|
||||
aElement.isOpened = false;
|
||||
aElement.children = null;
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Inspect a local object.
|
||||
*
|
||||
* @private
|
||||
* @param object aObject
|
||||
* The object you want to inspect.
|
||||
*/
|
||||
_inspectObject: function PTV__inspectObject(aObject)
|
||||
{
|
||||
this._objectCache = {};
|
||||
this._remoteObjectProvider = this._localObjectProvider.bind(this);
|
||||
let children = WebConsoleUtils.namesAndValuesOf(aObject, this._objectCache);
|
||||
this._updateRemoteObject(children, 0);
|
||||
return children;
|
||||
},
|
||||
|
||||
/**
|
||||
* An object provider for when the user inspects local objects (not remote
|
||||
* ones).
|
||||
*
|
||||
* @private
|
||||
* @param string aFromCacheId
|
||||
* The cache ID from where to retrieve the desired object.
|
||||
* @param string aObjectId
|
||||
* The ID of the object you want.
|
||||
* @param string aDestCacheId
|
||||
* The ID of the cache where to store any objects referenced by the
|
||||
* desired object.
|
||||
* @param function aCallback
|
||||
* The function you want to receive the object.
|
||||
*/
|
||||
_localObjectProvider:
|
||||
function PTV__localObjectProvider(aFromCacheId, aObjectId, aDestCacheId,
|
||||
aCallback)
|
||||
{
|
||||
let object = WebConsoleUtils.namesAndValuesOf(this._objectCache[aObjectId],
|
||||
this._objectCache);
|
||||
aCallback({cacheId: aFromCacheId,
|
||||
objectId: aObjectId,
|
||||
object: object,
|
||||
childrenCacheId: aDestCacheId || aFromCacheId,
|
||||
});
|
||||
},
|
||||
|
||||
/** nsITreeView interface implementation **/
|
||||
|
||||
selection: null,
|
||||
|
||||
get rowCount() { return this._rows.length; },
|
||||
setTree: function(treeBox) { this._treeBox = treeBox; },
|
||||
getCellText: function(idx, column) {
|
||||
let row = this._rows[idx];
|
||||
return row.name + ": " + row.value;
|
||||
},
|
||||
getLevel: function(idx) {
|
||||
return this._rows[idx].level;
|
||||
},
|
||||
isContainer: function(idx) {
|
||||
return !!this._rows[idx].inspectable;
|
||||
},
|
||||
isContainerOpen: function(idx) {
|
||||
return this._rows[idx].isOpened;
|
||||
},
|
||||
isContainerEmpty: function(idx) { return false; },
|
||||
isSeparator: function(idx) { return false; },
|
||||
isSorted: function() { return false; },
|
||||
isEditable: function(idx, column) { return false; },
|
||||
isSelectable: function(row, col) { return true; },
|
||||
|
||||
getParentIndex: function(idx)
|
||||
{
|
||||
if (this.getLevel(idx) == 0) {
|
||||
return -1;
|
||||
}
|
||||
for (var t = idx - 1; t >= 0; t--) {
|
||||
if (this.isContainer(t)) {
|
||||
return t;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
},
|
||||
|
||||
hasNextSibling: function(idx, after)
|
||||
{
|
||||
var thisLevel = this.getLevel(idx);
|
||||
return this._rows.slice(after + 1).some(function (r) r.level == thisLevel);
|
||||
},
|
||||
|
||||
toggleOpenState: function(idx)
|
||||
{
|
||||
let item = this._rows[idx];
|
||||
if (!item.inspectable) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (item.isOpened) {
|
||||
this._treeBox.beginUpdateBatch();
|
||||
item.isOpened = false;
|
||||
|
||||
var thisLevel = item.level;
|
||||
var t = idx + 1, deleteCount = 0;
|
||||
while (t < this._rows.length && this.getLevel(t++) > thisLevel) {
|
||||
deleteCount++;
|
||||
}
|
||||
|
||||
if (deleteCount) {
|
||||
this._rows.splice(idx + 1, deleteCount);
|
||||
this._treeBox.rowCountChanged(idx + 1, -deleteCount);
|
||||
}
|
||||
this._treeBox.invalidateRow(idx);
|
||||
this._treeBox.endUpdateBatch();
|
||||
}
|
||||
else {
|
||||
let levelUpdate = true;
|
||||
let callback = function _onRemoteResponse(aResponse) {
|
||||
this._treeBox.beginUpdateBatch();
|
||||
item.isOpened = true;
|
||||
|
||||
if (levelUpdate) {
|
||||
this._updateRemoteObject(aResponse.object, item.level + 1);
|
||||
item.children = aResponse.object;
|
||||
}
|
||||
|
||||
this._rows.splice.apply(this._rows, [idx + 1, 0].concat(item.children));
|
||||
|
||||
this._treeBox.rowCountChanged(idx + 1, item.children.length);
|
||||
this._treeBox.invalidateRow(idx);
|
||||
this._treeBox.endUpdateBatch();
|
||||
}.bind(this);
|
||||
|
||||
if (!item.children) {
|
||||
let fromCacheId = item.level > 0 ? this._panelCacheId :
|
||||
this._rootCacheId;
|
||||
this._remoteObjectProvider(fromCacheId, item.objectId,
|
||||
this._panelCacheId, callback);
|
||||
}
|
||||
else {
|
||||
levelUpdate = false;
|
||||
callback({object: item.children});
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
getImageSrc: function(idx, column) { },
|
||||
getProgressMode : function(idx,column) { },
|
||||
getCellValue: function(idx, column) { },
|
||||
cycleHeader: function(col, elem) { },
|
||||
selectionChanged: function() { },
|
||||
cycleCell: function(idx, column) { },
|
||||
performAction: function(action) { },
|
||||
performActionOnCell: function(action, index, column) { },
|
||||
performActionOnRow: function(action, row) { },
|
||||
getRowProperties: function(idx, column, prop) { },
|
||||
getCellProperties: function(idx, column, prop) { },
|
||||
getColumnProperties: function(column, element, prop) { },
|
||||
|
||||
setCellValue: function(row, col, value) { },
|
||||
setCellText: function(row, col, value) { },
|
||||
drop: function(index, orientation, dataTransfer) { },
|
||||
canDrop: function(index, orientation, dataTransfer) { return false; },
|
||||
|
||||
_cleanup: function PTV__cleanup()
|
||||
{
|
||||
if (this._rows.length) {
|
||||
// Reset the existing _rows children to the initial state.
|
||||
this._updateRemoteObject(this._rows, 0);
|
||||
this._rows = [];
|
||||
}
|
||||
|
||||
delete this._objectCache;
|
||||
delete this._rootCacheId;
|
||||
delete this._panelCacheId;
|
||||
delete this._remoteObjectProvider;
|
||||
},
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//// Helper for creating the panel.
|
||||
|
||||
/**
|
||||
* Creates a DOMNode and sets all the attributes of aAttributes on the created
|
||||
* element.
|
||||
*
|
||||
* @param nsIDOMDocument aDocument
|
||||
* Document to create the new DOMNode.
|
||||
* @param string aTag
|
||||
* Name of the tag for the DOMNode.
|
||||
* @param object aAttributes
|
||||
* Attributes set on the created DOMNode.
|
||||
* @returns nsIDOMNode
|
||||
*/
|
||||
function createElement(aDocument, aTag, aAttributes)
|
||||
{
|
||||
let node = aDocument.createElement(aTag);
|
||||
for (var attr in aAttributes) {
|
||||
node.setAttribute(attr, aAttributes[attr]);
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new DOMNode and appends it to aParent.
|
||||
*
|
||||
* @param nsIDOMDocument aDocument
|
||||
* Document to create the new DOMNode.
|
||||
* @param nsIDOMNode aParent
|
||||
* A parent node to append the created element.
|
||||
* @param string aTag
|
||||
* Name of the tag for the DOMNode.
|
||||
* @param object aAttributes
|
||||
* Attributes set on the created DOMNode.
|
||||
* @returns nsIDOMNode
|
||||
*/
|
||||
function appendChild(aDocument, aParent, aTag, aAttributes)
|
||||
{
|
||||
let node = createElement(aDocument, aTag, aAttributes);
|
||||
aParent.appendChild(node);
|
||||
return node;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//// PropertyPanel
|
||||
|
||||
/**
|
||||
* Creates a new PropertyPanel.
|
||||
*
|
||||
* @see PropertyTreeView
|
||||
* @param nsIDOMNode aParent
|
||||
* Parent node to append the created panel to.
|
||||
* @param string aTitle
|
||||
* Title for the panel.
|
||||
* @param string aObject
|
||||
* Object to display in the tree. For details about this object please
|
||||
* see the PropertyTreeView.data property in this file.
|
||||
* @param array of objects aButtons
|
||||
* Array with buttons to display at the bottom of the panel.
|
||||
*/
|
||||
function PropertyPanel(aParent, aTitle, aObject, aButtons)
|
||||
{
|
||||
let document = aParent.ownerDocument;
|
||||
|
||||
// Create the underlying panel
|
||||
this.panel = createElement(document, "panel", {
|
||||
label: aTitle,
|
||||
titlebar: "normal",
|
||||
noautofocus: "true",
|
||||
noautohide: "true",
|
||||
close: "true",
|
||||
});
|
||||
|
||||
// Create the tree.
|
||||
let tree = this.tree = createElement(document, "tree", {
|
||||
flex: 1,
|
||||
hidecolumnpicker: "true"
|
||||
});
|
||||
|
||||
let treecols = document.createElement("treecols");
|
||||
appendChild(document, treecols, "treecol", {
|
||||
primary: "true",
|
||||
flex: 1,
|
||||
hideheader: "true",
|
||||
ignoreincolumnpicker: "true"
|
||||
});
|
||||
tree.appendChild(treecols);
|
||||
|
||||
tree.appendChild(document.createElement("treechildren"));
|
||||
this.panel.appendChild(tree);
|
||||
|
||||
// Create the footer.
|
||||
let footer = createElement(document, "hbox", { align: "end" });
|
||||
appendChild(document, footer, "spacer", { flex: 1 });
|
||||
|
||||
// The footer can have butttons.
|
||||
let self = this;
|
||||
if (aButtons) {
|
||||
aButtons.forEach(function(button) {
|
||||
let buttonNode = appendChild(document, footer, "button", {
|
||||
label: button.label,
|
||||
accesskey: button.accesskey || "",
|
||||
class: button.class || "",
|
||||
});
|
||||
buttonNode.addEventListener("command", button.oncommand, false);
|
||||
});
|
||||
}
|
||||
|
||||
appendChild(document, footer, "resizer", { dir: "bottomend" });
|
||||
this.panel.appendChild(footer);
|
||||
|
||||
aParent.appendChild(this.panel);
|
||||
|
||||
// Create the treeView object.
|
||||
this.treeView = new PropertyTreeView();
|
||||
this.treeView.data = aObject;
|
||||
|
||||
// Set the treeView object on the tree view. This has to be done *after* the
|
||||
// panel is shown. This is because the tree binding must be attached first.
|
||||
this.panel.addEventListener("popupshown", function onPopupShow()
|
||||
{
|
||||
self.panel.removeEventListener("popupshown", onPopupShow, false);
|
||||
self.tree.view = self.treeView;
|
||||
}, false);
|
||||
|
||||
this.panel.addEventListener("popuphidden", function onPopupHide()
|
||||
{
|
||||
self.panel.removeEventListener("popuphidden", onPopupHide, false);
|
||||
self.destroy();
|
||||
}, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroy the PropertyPanel. This closes the panel and removes it from the
|
||||
* browser DOM.
|
||||
*/
|
||||
PropertyPanel.prototype.destroy = function PP_destroy()
|
||||
{
|
||||
this.treeView.data = null;
|
||||
this.panel.parentNode.removeChild(this.panel);
|
||||
this.treeView = null;
|
||||
this.panel = null;
|
||||
this.tree = null;
|
||||
}
|
||||
|
706
browser/devtools/webconsole/WebConsoleUtils.jsm
Normal file
706
browser/devtools/webconsole/WebConsoleUtils.jsm
Normal file
@ -0,0 +1,706 @@
|
||||
/* -*- Mode: js2; js2-basic-offset: 2; indent-tabs-mode: nil; -*- */
|
||||
/* vim: set ft=javascript 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");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
var EXPORTED_SYMBOLS = ["WebConsoleUtils"];
|
||||
|
||||
const STRINGS_URI = "chrome://browser/locale/devtools/webconsole.properties";
|
||||
|
||||
const TYPES = { OBJECT: 0,
|
||||
FUNCTION: 1,
|
||||
ARRAY: 2,
|
||||
OTHER: 3,
|
||||
ITERATOR: 4,
|
||||
GETTER: 5,
|
||||
GENERATOR: 6,
|
||||
STRING: 7
|
||||
};
|
||||
|
||||
var gObjectId = 0;
|
||||
|
||||
var WebConsoleUtils = {
|
||||
TYPES: TYPES,
|
||||
|
||||
/**
|
||||
* Convenience function to unwrap a wrapped object.
|
||||
*
|
||||
* @param aObject the object to unwrap.
|
||||
* @return aObject unwrapped.
|
||||
*/
|
||||
unwrap: function WCU_unwrap(aObject)
|
||||
{
|
||||
try {
|
||||
return XPCNativeWrapper.unwrap(aObject);
|
||||
}
|
||||
catch (ex) {
|
||||
return aObject;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Wrap a string in an nsISupportsString object.
|
||||
*
|
||||
* @param string aString
|
||||
* @return nsISupportsString
|
||||
*/
|
||||
supportsString: function WCU_supportsString(aString)
|
||||
{
|
||||
let str = Cc["@mozilla.org/supports-string;1"].
|
||||
createInstance(Ci.nsISupportsString);
|
||||
str.data = aString;
|
||||
return str;
|
||||
},
|
||||
|
||||
/**
|
||||
* Clone an object.
|
||||
*
|
||||
* @param object aObject
|
||||
* The object you want cloned.
|
||||
* @param boolean aRecursive
|
||||
* Tells if you want to dig deeper into the object, to clone
|
||||
* recursively.
|
||||
* @param function [aFilter]
|
||||
* Optional, filter function, called for every property. Three
|
||||
* arguments are passed: key, value and object. Return true if the
|
||||
* property should be added to the cloned object. Return false to skip
|
||||
* the property.
|
||||
* @return object
|
||||
* The cloned object.
|
||||
*/
|
||||
cloneObject: function WCU_cloneObject(aObject, aRecursive, aFilter)
|
||||
{
|
||||
if (typeof aObject != "object") {
|
||||
return aObject;
|
||||
}
|
||||
|
||||
let temp;
|
||||
|
||||
if (Array.isArray(aObject)) {
|
||||
temp = [];
|
||||
Array.forEach(aObject, function(aValue, aIndex) {
|
||||
if (!aFilter || aFilter(aIndex, aValue, aObject)) {
|
||||
temp.push(aRecursive ? WCU_cloneObject(aValue) : aValue);
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
temp = {};
|
||||
for (let key in aObject) {
|
||||
let value = aObject[key];
|
||||
if (aObject.hasOwnProperty(key) &&
|
||||
(!aFilter || aFilter(key, value, aObject))) {
|
||||
temp[key] = aRecursive ? WCU_cloneObject(value) : value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return temp;
|
||||
},
|
||||
|
||||
/**
|
||||
* Gets the ID of the inner window of this DOM window.
|
||||
*
|
||||
* @param nsIDOMWindow aWindow
|
||||
* @return integer
|
||||
* Inner ID for the given aWindow.
|
||||
*/
|
||||
getInnerWindowId: function WCU_getInnerWindowId(aWindow)
|
||||
{
|
||||
return aWindow.QueryInterface(Ci.nsIInterfaceRequestor).
|
||||
getInterface(Ci.nsIDOMWindowUtils).currentInnerWindowID;
|
||||
},
|
||||
|
||||
/**
|
||||
* Gets the ID of the outer window of this DOM window.
|
||||
*
|
||||
* @param nsIDOMWindow aWindow
|
||||
* @return integer
|
||||
* Outer ID for the given aWindow.
|
||||
*/
|
||||
getOuterWindowId: function WCU_getOuterWindowId(aWindow)
|
||||
{
|
||||
return aWindow.QueryInterface(Ci.nsIInterfaceRequestor).
|
||||
getInterface(Ci.nsIDOMWindowUtils).outerWindowID;
|
||||
},
|
||||
|
||||
/**
|
||||
* Gets the window that has the given outer ID.
|
||||
*
|
||||
* @param integer aOuterId
|
||||
* @param nsIDOMWindow [aHintWindow]
|
||||
* Optional, the window object used to QueryInterface to
|
||||
* nsIDOMWindowUtils. If this is not given,
|
||||
* Services.wm.getMostRecentWindow() is used.
|
||||
* @return nsIDOMWindow|null
|
||||
* The window object with the given outer ID.
|
||||
*/
|
||||
getWindowByOuterId: function WCU_getWindowByOuterId(aOuterId, aHintWindow)
|
||||
{
|
||||
let someWindow = aHintWindow || Services.wm.getMostRecentWindow(null);
|
||||
let content = null;
|
||||
|
||||
if (someWindow) {
|
||||
let windowUtils = someWindow.QueryInterface(Ci.nsIInterfaceRequestor).
|
||||
getInterface(Ci.nsIDOMWindowUtils);
|
||||
content = windowUtils.getOuterWindowWithId(aOuterId);
|
||||
}
|
||||
|
||||
return content;
|
||||
},
|
||||
|
||||
/**
|
||||
* Gets the window that has the given inner ID.
|
||||
*
|
||||
* @param integer aInnerId
|
||||
* @param nsIDOMWindow [aHintWindow]
|
||||
* Optional, the window object used to QueryInterface to
|
||||
* nsIDOMWindowUtils. If this is not given,
|
||||
* Services.wm.getMostRecentWindow() is used.
|
||||
* @return nsIDOMWindow|null
|
||||
* The window object with the given inner ID.
|
||||
*/
|
||||
getWindowByInnerId: function WCU_getWindowByInnerId(aInnerId, aHintWindow)
|
||||
{
|
||||
let someWindow = aHintWindow || Services.wm.getMostRecentWindow(null);
|
||||
let content = null;
|
||||
|
||||
if (someWindow) {
|
||||
let windowUtils = someWindow.QueryInterface(Ci.nsIInterfaceRequestor).
|
||||
getInterface(Ci.nsIDOMWindowUtils);
|
||||
content = windowUtils.getInnerWindowWithId(aInnerId);
|
||||
}
|
||||
|
||||
return content;
|
||||
},
|
||||
|
||||
/**
|
||||
* Abbreviates the given source URL so that it can be displayed flush-right
|
||||
* without being too distracting.
|
||||
*
|
||||
* @param string aSourceURL
|
||||
* The source URL to shorten.
|
||||
* @return string
|
||||
* The abbreviated form of the source URL.
|
||||
*/
|
||||
abbreviateSourceURL: function WCU_abbreviateSourceURL(aSourceURL)
|
||||
{
|
||||
// Remove any query parameters.
|
||||
let hookIndex = aSourceURL.indexOf("?");
|
||||
if (hookIndex > -1) {
|
||||
aSourceURL = aSourceURL.substring(0, hookIndex);
|
||||
}
|
||||
|
||||
// Remove a trailing "/".
|
||||
if (aSourceURL[aSourceURL.length - 1] == "/") {
|
||||
aSourceURL = aSourceURL.substring(0, aSourceURL.length - 1);
|
||||
}
|
||||
|
||||
// Remove all but the last path component.
|
||||
let slashIndex = aSourceURL.lastIndexOf("/");
|
||||
if (slashIndex > -1) {
|
||||
aSourceURL = aSourceURL.substring(slashIndex + 1);
|
||||
}
|
||||
|
||||
return aSourceURL;
|
||||
},
|
||||
|
||||
/**
|
||||
* Format the jsterm execution result based on its type.
|
||||
*
|
||||
* @param mixed aResult
|
||||
* The evaluation result object you want displayed.
|
||||
* @return string
|
||||
* The string that can be displayed.
|
||||
*/
|
||||
formatResult: function WCU_formatResult(aResult)
|
||||
{
|
||||
let output = "";
|
||||
let type = this.getResultType(aResult);
|
||||
|
||||
switch (type) {
|
||||
case "string":
|
||||
output = this.formatResultString(aResult);
|
||||
break;
|
||||
case "boolean":
|
||||
case "date":
|
||||
case "error":
|
||||
case "number":
|
||||
case "regexp":
|
||||
output = aResult.toString();
|
||||
break;
|
||||
case "null":
|
||||
case "undefined":
|
||||
output = type;
|
||||
break;
|
||||
default:
|
||||
if (aResult.toSource) {
|
||||
try {
|
||||
output = aResult.toSource();
|
||||
} catch (ex) { }
|
||||
}
|
||||
if (!output || output == "({})") {
|
||||
output = aResult.toString();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return output;
|
||||
},
|
||||
|
||||
/**
|
||||
* Format a string for output.
|
||||
*
|
||||
* @param string aString
|
||||
* The string you want to display.
|
||||
* @return string
|
||||
* The string that can be displayed.
|
||||
*/
|
||||
formatResultString: function WCU_formatResultString(aString)
|
||||
{
|
||||
function isControlCode(c) {
|
||||
// See http://en.wikipedia.org/wiki/C0_and_C1_control_codes
|
||||
// C0 is 0x00-0x1F, C1 is 0x80-0x9F (inclusive).
|
||||
// We also include DEL (U+007F) and NBSP (U+00A0), which are not strictly
|
||||
// in C1 but border it.
|
||||
return (c <= 0x1F) || (0x7F <= c && c <= 0xA0);
|
||||
}
|
||||
|
||||
function replaceFn(aMatch, aType, aHex) {
|
||||
// Leave control codes escaped, but unescape the rest of the characters.
|
||||
let c = parseInt(aHex, 16);
|
||||
return isControlCode(c) ? aMatch : String.fromCharCode(c);
|
||||
}
|
||||
|
||||
let output = uneval(aString).replace(/\\(x)([0-9a-fA-F]{2})/g, replaceFn)
|
||||
.replace(/\\(u)([0-9a-fA-F]{4})/g, replaceFn);
|
||||
|
||||
return output;
|
||||
},
|
||||
|
||||
/**
|
||||
* Determine if an object can be inspected or not.
|
||||
*
|
||||
* @param mixed aObject
|
||||
* The object you want to check if it can be inspected.
|
||||
* @return boolean
|
||||
* True if the object is inspectable or false otherwise.
|
||||
*/
|
||||
isObjectInspectable: function WCU_isObjectInspectable(aObject)
|
||||
{
|
||||
let isEnumerable = false;
|
||||
|
||||
// Skip Iterators and Generators.
|
||||
if (this.isIteratorOrGenerator(aObject)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
for (let p in aObject) {
|
||||
isEnumerable = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch (ex) {
|
||||
// Proxy objects can lack an enumerable method.
|
||||
}
|
||||
|
||||
return isEnumerable && typeof(aObject) != "string";
|
||||
},
|
||||
|
||||
/**
|
||||
* Determine the type of the jsterm execution result.
|
||||
*
|
||||
* @param mixed aResult
|
||||
* The evaluation result object you want to check.
|
||||
* @return string
|
||||
* Constructor name or type: string, number, boolean, regexp, date,
|
||||
* function, object, null, undefined...
|
||||
*/
|
||||
getResultType: function WCU_getResultType(aResult)
|
||||
{
|
||||
let type = aResult === null ? "null" : typeof aResult;
|
||||
if (type == "object" && aResult.constructor && aResult.constructor.name) {
|
||||
type = aResult.constructor.name;
|
||||
}
|
||||
|
||||
return type.toLowerCase();
|
||||
},
|
||||
|
||||
/**
|
||||
* Figures out the type of aObject and the string to display as the object
|
||||
* value.
|
||||
*
|
||||
* @see TYPES
|
||||
* @param object aObject
|
||||
* The object to operate on.
|
||||
* @return object
|
||||
* An object of the form:
|
||||
* {
|
||||
* type: TYPES.OBJECT || TYPES.FUNCTION || ...
|
||||
* display: string for displaying the object
|
||||
* }
|
||||
*/
|
||||
presentableValueFor: function WCU_presentableValueFor(aObject)
|
||||
{
|
||||
let type = this.getResultType(aObject);
|
||||
let presentable;
|
||||
|
||||
switch (type) {
|
||||
case "undefined":
|
||||
case "null":
|
||||
return {
|
||||
type: TYPES.OTHER,
|
||||
display: type
|
||||
};
|
||||
|
||||
case "array":
|
||||
return {
|
||||
type: TYPES.ARRAY,
|
||||
display: "Array"
|
||||
};
|
||||
|
||||
case "string":
|
||||
return {
|
||||
type: TYPES.STRING,
|
||||
display: "\"" + aObject + "\""
|
||||
};
|
||||
|
||||
case "date":
|
||||
case "regexp":
|
||||
case "number":
|
||||
case "boolean":
|
||||
return {
|
||||
type: TYPES.OTHER,
|
||||
display: aObject.toString()
|
||||
};
|
||||
|
||||
case "iterator":
|
||||
return {
|
||||
type: TYPES.ITERATOR,
|
||||
display: "Iterator"
|
||||
};
|
||||
|
||||
case "function":
|
||||
presentable = aObject.toString();
|
||||
return {
|
||||
type: TYPES.FUNCTION,
|
||||
display: presentable.substring(0, presentable.indexOf(')') + 1)
|
||||
};
|
||||
|
||||
default:
|
||||
presentable = String(aObject);
|
||||
let m = /^\[object (\S+)\]/.exec(presentable);
|
||||
|
||||
try {
|
||||
if (type == "object" && typeof aObject.next == "function" &&
|
||||
m && m[1] == "Generator") {
|
||||
return {
|
||||
type: TYPES.GENERATOR,
|
||||
display: m[1]
|
||||
};
|
||||
}
|
||||
}
|
||||
catch (ex) {
|
||||
// window.history.next throws in the typeof check above.
|
||||
return {
|
||||
type: TYPES.OBJECT,
|
||||
display: m ? m[1] : "Object"
|
||||
};
|
||||
}
|
||||
|
||||
if (type == "object" && typeof aObject.__iterator__ == "function") {
|
||||
return {
|
||||
type: TYPES.ITERATOR,
|
||||
display: "Iterator"
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
type: TYPES.OBJECT,
|
||||
display: m ? m[1] : "Object"
|
||||
};
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Tells if the given function is native or not.
|
||||
*
|
||||
* @param function aFunction
|
||||
* The function you want to check if it is native or not.
|
||||
* @return boolean
|
||||
* True if the given function is native, false otherwise.
|
||||
*/
|
||||
isNativeFunction: function WCU_isNativeFunction(aFunction)
|
||||
{
|
||||
return typeof aFunction == "function" && !("prototype" in aFunction);
|
||||
},
|
||||
|
||||
/**
|
||||
* Tells if the given property of the provided object is a non-native getter or
|
||||
* not.
|
||||
*
|
||||
* @param object aObject
|
||||
* The object that contains the property.
|
||||
* @param string aProp
|
||||
* The property you want to check if it is a getter or not.
|
||||
* @return boolean
|
||||
* True if the given property is a getter, false otherwise.
|
||||
*/
|
||||
isNonNativeGetter: function WCU_isNonNativeGetter(aObject, aProp)
|
||||
{
|
||||
if (typeof aObject != "object") {
|
||||
return false;
|
||||
}
|
||||
let desc;
|
||||
while (aObject) {
|
||||
try {
|
||||
if (desc = Object.getOwnPropertyDescriptor(aObject, aProp)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch (ex) {
|
||||
// Native getters throw here. See bug 520882.
|
||||
if (ex.name == "NS_ERROR_XPC_BAD_CONVERT_JS" ||
|
||||
ex.name == "NS_ERROR_XPC_BAD_OP_ON_WN_PROTO") {
|
||||
return false;
|
||||
}
|
||||
throw ex;
|
||||
}
|
||||
aObject = Object.getPrototypeOf(aObject);
|
||||
}
|
||||
if (desc && desc.get && !this.isNativeFunction(desc.get)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
/**
|
||||
* Get an array that describes the properties of the given object.
|
||||
*
|
||||
* @param object aObject
|
||||
* The object to get the properties from.
|
||||
* @param object aObjectCache
|
||||
* Optional object cache where to store references to properties of
|
||||
* aObject that are inspectable. See this.isObjectInspectable().
|
||||
* @return array
|
||||
* An array that describes each property from the given object. Each
|
||||
* array element is an object (a property descriptor). Each property
|
||||
* descriptor has the following properties:
|
||||
* - name - property name
|
||||
* - value - a presentable property value representation (see
|
||||
* this.presentableValueFor())
|
||||
* - type - value type (see this.presentableValueFor())
|
||||
* - inspectable - tells if the property value holds further
|
||||
* properties (see this.isObjectInspectable()).
|
||||
* - objectId - optional, available only if aObjectCache is given and
|
||||
* if |inspectable| is true. You can do
|
||||
* aObjectCache[propertyDescriptor.objectId] to get the actual object
|
||||
* referenced by the property of aObject.
|
||||
*/
|
||||
namesAndValuesOf: function WCU_namesAndValuesOf(aObject, aObjectCache)
|
||||
{
|
||||
let pairs = [];
|
||||
let value, presentable;
|
||||
|
||||
let isDOMDocument = aObject instanceof Ci.nsIDOMDocument;
|
||||
|
||||
for (let propName in aObject) {
|
||||
// See bug 632275: skip deprecated width and height properties.
|
||||
if (isDOMDocument && (propName == "width" || propName == "height")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Also skip non-native getters.
|
||||
if (this.isNonNativeGetter(aObject, propName)) {
|
||||
value = "";
|
||||
presentable = {type: TYPES.GETTER, display: "Getter"};
|
||||
}
|
||||
else {
|
||||
value = aObject[propName];
|
||||
presentable = this.presentableValueFor(value);
|
||||
}
|
||||
|
||||
let pair = {};
|
||||
pair.name = propName;
|
||||
pair.value = presentable.display;
|
||||
pair.inspectable = false;
|
||||
pair.type = presentable.type;
|
||||
|
||||
switch (presentable.type) {
|
||||
case TYPES.GETTER:
|
||||
case TYPES.ITERATOR:
|
||||
case TYPES.GENERATOR:
|
||||
case TYPES.STRING:
|
||||
break;
|
||||
default:
|
||||
try {
|
||||
for (let p in value) {
|
||||
pair.inspectable = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch (ex) { }
|
||||
break;
|
||||
}
|
||||
|
||||
// Store the inspectable object.
|
||||
if (pair.inspectable && aObjectCache) {
|
||||
pair.objectId = ++gObjectId;
|
||||
aObjectCache[pair.objectId] = value;
|
||||
}
|
||||
|
||||
pairs.push(pair);
|
||||
}
|
||||
|
||||
pairs.sort(function(a, b)
|
||||
{
|
||||
// Convert the pair.name to a number for later sorting.
|
||||
let aNumber = parseFloat(a.name);
|
||||
let bNumber = parseFloat(b.name);
|
||||
|
||||
// Sort numbers.
|
||||
if (!isNaN(aNumber) && isNaN(bNumber)) {
|
||||
return -1;
|
||||
}
|
||||
else if (isNaN(aNumber) && !isNaN(bNumber)) {
|
||||
return 1;
|
||||
}
|
||||
else if (!isNaN(aNumber) && !isNaN(bNumber)) {
|
||||
return aNumber - bNumber;
|
||||
}
|
||||
// Sort string.
|
||||
else if (a.name < b.name) {
|
||||
return -1;
|
||||
}
|
||||
else if (a.name > b.name) {
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
});
|
||||
|
||||
return pairs;
|
||||
},
|
||||
|
||||
/**
|
||||
* Check if the given object is an iterator or a generator.
|
||||
*
|
||||
* @param object aObject
|
||||
* The object you want to check.
|
||||
* @return boolean
|
||||
* True if the given object is an iterator or a generator, otherwise
|
||||
* false is returned.
|
||||
*/
|
||||
isIteratorOrGenerator: function WCU_isIteratorOrGenerator(aObject)
|
||||
{
|
||||
if (aObject === null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (typeof aObject == "object") {
|
||||
if (typeof aObject.__iterator__ == "function" ||
|
||||
aObject.constructor && aObject.constructor.name == "Iterator") {
|
||||
return true;
|
||||
}
|
||||
|
||||
try {
|
||||
let str = aObject.toString();
|
||||
if (typeof aObject.next == "function" &&
|
||||
str.indexOf("[object Generator") == 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
catch (ex) {
|
||||
// window.history.next throws in the typeof check above.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
},
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Localization
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
WebConsoleUtils.l10n = {
|
||||
/**
|
||||
* Generates a formatted timestamp string for displaying in console messages.
|
||||
*
|
||||
* @param integer [aMilliseconds]
|
||||
* Optional, allows you to specify the timestamp in milliseconds since
|
||||
* the UNIX epoch.
|
||||
* @return string
|
||||
* The timestamp formatted for display.
|
||||
*/
|
||||
timestampString: function WCU_l10n_timestampString(aMilliseconds)
|
||||
{
|
||||
let d = new Date(aMilliseconds ? aMilliseconds : null);
|
||||
let hours = d.getHours(), minutes = d.getMinutes();
|
||||
let seconds = d.getSeconds(), milliseconds = d.getMilliseconds();
|
||||
let parameters = [hours, minutes, seconds, milliseconds];
|
||||
return this.getFormatStr("timestampFormat", parameters);
|
||||
},
|
||||
|
||||
/**
|
||||
* Retrieve a localized string.
|
||||
*
|
||||
* @param string aName
|
||||
* The string name you want from the Web Console string bundle.
|
||||
* @return string
|
||||
* The localized string.
|
||||
*/
|
||||
getStr: function WCU_l10n_getStr(aName)
|
||||
{
|
||||
let result;
|
||||
try {
|
||||
result = this.stringBundle.GetStringFromName(aName);
|
||||
}
|
||||
catch (ex) {
|
||||
Cu.reportError("Failed to get string: " + aName);
|
||||
throw ex;
|
||||
}
|
||||
return result;
|
||||
},
|
||||
|
||||
/**
|
||||
* Retrieve a localized string formatted with values coming from the given
|
||||
* array.
|
||||
*
|
||||
* @param string aName
|
||||
* The string name you want from the Web Console string bundle.
|
||||
* @param array aArray
|
||||
* The array of values you want in the formatted string.
|
||||
* @return string
|
||||
* The formatted local string.
|
||||
*/
|
||||
getFormatStr: function WCU_l10n_getFormatStr(aName, aArray)
|
||||
{
|
||||
let result;
|
||||
try {
|
||||
result = this.stringBundle.formatStringFromName(aName, aArray, aArray.length);
|
||||
}
|
||||
catch (ex) {
|
||||
Cu.reportError("Failed to format string: " + aName);
|
||||
throw ex;
|
||||
}
|
||||
return result;
|
||||
},
|
||||
};
|
||||
|
||||
XPCOMUtils.defineLazyGetter(WebConsoleUtils.l10n, "stringBundle", function() {
|
||||
return Services.strings.createBundle(STRINGS_URI);
|
||||
});
|
@ -44,8 +44,7 @@ function test()
|
||||
|
||||
expectUncaughtException();
|
||||
|
||||
gBrowser.selectedTab = gBrowser.addTab(TEST_URI);
|
||||
|
||||
addTab(TEST_URI);
|
||||
gBrowser.selectedBrowser.addEventListener("load", function onLoad() {
|
||||
gBrowser.selectedBrowser.removeEventListener("load", onLoad, true);
|
||||
testOpenUI(true);
|
||||
@ -57,27 +56,26 @@ function testOpenUI(aTestReopen)
|
||||
// test to see if the messages are
|
||||
// displayed when the console UI is opened
|
||||
|
||||
HUDService.activateHUDForContext(gBrowser.selectedTab);
|
||||
let hudId = HUDService.getHudIdByWindow(content);
|
||||
let hud = HUDService.getHudReferenceById(hudId);
|
||||
openConsole(null, function(hud) {
|
||||
testLogEntry(hud.outputNode, "log Bazzle",
|
||||
"Find a console log entry from before console UI is opened",
|
||||
false, null);
|
||||
|
||||
testLogEntry(hud.outputNode, "log Bazzle",
|
||||
"Find a console log entry from before console UI is opened",
|
||||
false, null);
|
||||
testLogEntry(hud.outputNode, "error Bazzle",
|
||||
"Find a console error entry from before console UI is opened",
|
||||
false, null);
|
||||
|
||||
testLogEntry(hud.outputNode, "error Bazzle",
|
||||
"Find a console error entry from before console UI is opened",
|
||||
false, null);
|
||||
testLogEntry(hud.outputNode, "bazBug611032", "Found the JavaScript error");
|
||||
testLogEntry(hud.outputNode, "cssColorBug611032", "Found the CSS error");
|
||||
|
||||
testLogEntry(hud.outputNode, "bazBug611032", "Found the JavaScript error");
|
||||
testLogEntry(hud.outputNode, "cssColorBug611032", "Found the CSS error");
|
||||
|
||||
HUDService.deactivateHUDForContext(gBrowser.selectedTab);
|
||||
|
||||
if (aTestReopen) {
|
||||
HUDService.deactivateHUDForContext(gBrowser.selectedTab);
|
||||
executeSoon(testOpenUI);
|
||||
} else {
|
||||
executeSoon(finish);
|
||||
}
|
||||
|
||||
if (aTestReopen) {
|
||||
HUDService.deactivateHUDForContext(gBrowser.selectedTab);
|
||||
executeSoon(testOpenUI);
|
||||
}
|
||||
else {
|
||||
executeSoon(finish);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -15,7 +15,7 @@ function test() {
|
||||
}
|
||||
|
||||
function testAbbreviation(aFullURL, aAbbreviatedURL) {
|
||||
is(ConsoleUtils.abbreviateSourceURL(aFullURL), aAbbreviatedURL, aFullURL +
|
||||
is(WebConsoleUtils.abbreviateSourceURL(aFullURL), aAbbreviatedURL, aFullURL +
|
||||
" is abbreviated to " + aAbbreviatedURL);
|
||||
}
|
||||
|
||||
|
@ -51,33 +51,26 @@ function test() {
|
||||
// see bug 580030: the error handler fails silently after page reload.
|
||||
// https://bugzilla.mozilla.org/show_bug.cgi?id=580030
|
||||
function onLoad(aEvent) {
|
||||
browser.removeEventListener(aEvent.type, arguments.callee, true);
|
||||
browser.removeEventListener(aEvent.type, onLoad, true);
|
||||
|
||||
openConsole();
|
||||
|
||||
browser.addEventListener("load", testErrorsAfterPageReload, true);
|
||||
executeSoon(function() {
|
||||
openConsole(null, function(hud) {
|
||||
hud.jsterm.clearOutput();
|
||||
browser.addEventListener("load", testErrorsAfterPageReload, true);
|
||||
content.location.reload();
|
||||
});
|
||||
}
|
||||
|
||||
function testErrorsAfterPageReload(aEvent) {
|
||||
browser.removeEventListener(aEvent.type, arguments.callee, true);
|
||||
browser.removeEventListener(aEvent.type, testErrorsAfterPageReload, true);
|
||||
|
||||
// dispatch a click event to the button in the test page and listen for
|
||||
// errors.
|
||||
|
||||
Services.console.registerListener(consoleObserver);
|
||||
|
||||
var button = content.document.querySelector("button").wrappedJSObject;
|
||||
var clickEvent = content.document.createEvent("MouseEvents");
|
||||
clickEvent.initMouseEvent("click", true, true,
|
||||
content, 0, 0, 0, 0, 0, false, false,
|
||||
false, false, 0, null);
|
||||
|
||||
executeSoon(function() {
|
||||
button.dispatchEvent(clickEvent);
|
||||
});
|
||||
let button = content.document.querySelector("button").wrappedJSObject;
|
||||
ok(button, "button found");
|
||||
EventUtils.sendMouseEvent({type: "click"}, button, content);
|
||||
}
|
||||
|
||||
var consoleObserver = {
|
||||
@ -95,10 +88,14 @@ var consoleObserver = {
|
||||
|
||||
let outputNode = HUDService.getHudByWindow(content).outputNode;
|
||||
|
||||
executeSoon(function() {
|
||||
let msg = "Found the error message after page reload";
|
||||
testLogEntry(outputNode, "fooBazBaz", msg);
|
||||
finishTest();
|
||||
waitForSuccess({
|
||||
name: "error message after page reload",
|
||||
validatorFn: function()
|
||||
{
|
||||
return outputNode.textContent.indexOf("fooBazBaz") > -1;
|
||||
},
|
||||
successFn: finishTest,
|
||||
failureFn: finishTest,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
@ -21,7 +21,7 @@ function test() {
|
||||
browser.removeEventListener("DOMContentLoaded", testTimestamp, false);
|
||||
const TEST_TIMESTAMP = 12345678;
|
||||
let date = new Date(TEST_TIMESTAMP);
|
||||
let localizedString = ConsoleUtils.timestampString(TEST_TIMESTAMP);
|
||||
let localizedString = WebConsoleUtils.l10n.timestampString(TEST_TIMESTAMP);
|
||||
isnot(localizedString.indexOf(date.getHours()), -1, "the localized " +
|
||||
"timestamp contains the hours");
|
||||
isnot(localizedString.indexOf(date.getMinutes()), -1, "the localized " +
|
||||
|
@ -52,14 +52,14 @@ function test() {
|
||||
function testDuplicateErrors() {
|
||||
browser.removeEventListener("DOMContentLoaded", testDuplicateErrors,
|
||||
false);
|
||||
openConsole();
|
||||
openConsole(null, function(hud) {
|
||||
hud.jsterm.clearOutput();
|
||||
|
||||
HUDService.getHudByWindow(content).jsterm.clearOutput();
|
||||
Services.console.registerListener(consoleObserver);
|
||||
|
||||
Services.console.registerListener(consoleObserver);
|
||||
|
||||
expectUncaughtException();
|
||||
content.location.reload();
|
||||
expectUncaughtException();
|
||||
content.location.reload();
|
||||
});
|
||||
}
|
||||
|
||||
var consoleObserver = {
|
||||
@ -77,18 +77,27 @@ var consoleObserver = {
|
||||
|
||||
outputNode = HUDService.getHudByWindow(content).outputNode;
|
||||
|
||||
executeSoon(function () {
|
||||
var text = outputNode.textContent;
|
||||
var error1pos = text.indexOf("fooDuplicateError1");
|
||||
ok(error1pos > -1, "found fooDuplicateError1");
|
||||
if (error1pos > -1) {
|
||||
ok(text.indexOf("fooDuplicateError1", error1pos + 1) == -1,
|
||||
"no duplicate for fooDuplicateError1");
|
||||
}
|
||||
waitForSuccess({
|
||||
name: "fooDuplicateError1 error displayed",
|
||||
validatorFn: function()
|
||||
{
|
||||
return outputNode.textContent.indexOf("fooDuplicateError1") > -1;
|
||||
},
|
||||
successFn: function()
|
||||
{
|
||||
let text = outputNode.textContent;
|
||||
let error1pos = text.indexOf("fooDuplicateError1");
|
||||
ok(error1pos > -1, "found fooDuplicateError1");
|
||||
if (error1pos > -1) {
|
||||
ok(text.indexOf("fooDuplicateError1", error1pos + 1) == -1,
|
||||
"no duplicate for fooDuplicateError1");
|
||||
}
|
||||
|
||||
findLogEntry("test-duplicate-error.html");
|
||||
findLogEntry("test-duplicate-error.html");
|
||||
|
||||
finishTest();
|
||||
finishTest();
|
||||
},
|
||||
failureFn: finishTest,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
@ -12,33 +12,67 @@
|
||||
// Tests that the Web Console limits the number of lines displayed according to
|
||||
// the user's preferences.
|
||||
|
||||
const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/test-console.html";
|
||||
const TEST_URI = "data:text/html;charset=utf8,test for bug 585237";
|
||||
let hud, testDriver;
|
||||
|
||||
function test() {
|
||||
addTab(TEST_URI);
|
||||
browser.addEventListener("DOMContentLoaded", testLineLimit,
|
||||
false);
|
||||
browser.addEventListener("load", function onLoad() {
|
||||
browser.removeEventListener("load", onLoad, true);
|
||||
openConsole(null, function(aHud) {
|
||||
hud = aHud;
|
||||
testDriver = testGen();
|
||||
testNext();
|
||||
});
|
||||
}, true);
|
||||
}
|
||||
|
||||
function testLineLimit() {
|
||||
browser.removeEventListener("DOMContentLoaded",testLineLimit, false);
|
||||
function testNext() {
|
||||
testDriver.next();
|
||||
}
|
||||
|
||||
openConsole();
|
||||
function testGen() {
|
||||
let console = content.console;
|
||||
outputNode = hud.outputNode;
|
||||
|
||||
let console = browser.contentWindow.wrappedJSObject.console;
|
||||
outputNode = HUDService.getHudByWindow(content).outputNode;
|
||||
hud.jsterm.clearOutput();
|
||||
|
||||
let prefBranch = Services.prefs.getBranch("devtools.hud.loglimit.");
|
||||
prefBranch.setIntPref("console", 20);
|
||||
|
||||
for (let i = 0; i < 20; i++) {
|
||||
for (let i = 0; i < 30; i++) {
|
||||
console.log("foo #" + i); // must change message to prevent repeats
|
||||
}
|
||||
|
||||
waitForSuccess({
|
||||
name: "20 console.log messages displayed",
|
||||
validatorFn: function()
|
||||
{
|
||||
return outputNode.textContent.indexOf("foo #29") > -1;
|
||||
},
|
||||
successFn: testNext,
|
||||
failureFn: finishTest,
|
||||
});
|
||||
|
||||
yield;
|
||||
|
||||
is(countMessageNodes(), 20, "there are 20 message nodes in the output " +
|
||||
"when the log limit is set to 20");
|
||||
|
||||
console.log("bar");
|
||||
console.log("bar bug585237");
|
||||
|
||||
waitForSuccess({
|
||||
name: "another console.log message displayed",
|
||||
validatorFn: function()
|
||||
{
|
||||
return outputNode.textContent.indexOf("bar bug585237") > -1;
|
||||
},
|
||||
successFn: testNext,
|
||||
failureFn: finishTest,
|
||||
});
|
||||
|
||||
yield;
|
||||
|
||||
is(countMessageNodes(), 20, "there are still 20 message nodes in the " +
|
||||
"output when adding one more");
|
||||
|
||||
@ -47,17 +81,41 @@ function testLineLimit() {
|
||||
console.log("boo #" + i); // must change message to prevent repeats
|
||||
}
|
||||
|
||||
waitForSuccess({
|
||||
name: "another 20 console.log message displayed",
|
||||
validatorFn: function()
|
||||
{
|
||||
return outputNode.textContent.indexOf("boo #19") > -1;
|
||||
},
|
||||
successFn: testNext,
|
||||
failureFn: finishTest,
|
||||
});
|
||||
|
||||
yield;
|
||||
|
||||
is(countMessageNodes(), 30, "there are 30 message nodes in the output " +
|
||||
"when the log limit is set to 30");
|
||||
|
||||
prefBranch.setIntPref("console", 0);
|
||||
console.log("baz");
|
||||
is(countMessageNodes(), 0, "there are no message nodes in the output when " +
|
||||
"the log limit is set to zero");
|
||||
|
||||
waitForSuccess({
|
||||
name: "clear output",
|
||||
validatorFn: function()
|
||||
{
|
||||
return countMessageNodes() == 0;
|
||||
},
|
||||
successFn: testNext,
|
||||
failureFn: finishTest,
|
||||
});
|
||||
|
||||
yield;
|
||||
|
||||
prefBranch.clearUserPref("console");
|
||||
prefBranch = console = outputNode = null;
|
||||
hud = testDriver = prefBranch = console = outputNode = null;
|
||||
finishTest();
|
||||
|
||||
yield;
|
||||
}
|
||||
|
||||
function countMessageNodes() {
|
||||
|
@ -46,10 +46,10 @@ function test() {
|
||||
function tabLoaded() {
|
||||
browser.removeEventListener("load", tabLoaded, true);
|
||||
|
||||
openConsole();
|
||||
|
||||
browser.addEventListener("load", tabReloaded, true);
|
||||
content.location.reload();
|
||||
openConsole(null, function() {
|
||||
browser.addEventListener("load", tabReloaded, true);
|
||||
content.location.reload();
|
||||
});
|
||||
}
|
||||
|
||||
function tabReloaded() {
|
||||
|
@ -12,45 +12,49 @@ const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/te
|
||||
|
||||
function test() {
|
||||
addTab(TEST_URI);
|
||||
browser.addEventListener("load", tabLoaded, true);
|
||||
browser.addEventListener("load", function onLoad() {
|
||||
browser.removeEventListener("load", onLoad, true);
|
||||
openConsole(null, consoleOpened);
|
||||
}, true);
|
||||
}
|
||||
|
||||
function tabLoaded() {
|
||||
browser.removeEventListener("load", tabLoaded, true);
|
||||
openConsole();
|
||||
|
||||
function consoleOpened(HUD) {
|
||||
// See bugs 574036, 586386 and 587617.
|
||||
|
||||
let HUD = HUDService.getHudByWindow(content);
|
||||
outputNode = HUD.outputNode;
|
||||
let selection = getSelection();
|
||||
let jstermInput = HUD.jsterm.inputNode;
|
||||
let console = content.wrappedJSObject.console;
|
||||
let contentSelection = content.wrappedJSObject.getSelection();
|
||||
|
||||
let make_selection = function () {
|
||||
let controller =
|
||||
top.document.commandDispatcher.
|
||||
getControllerForCommand("cmd_copy");
|
||||
is(controller.isCommandEnabled("cmd_copy"), false, "cmd_copy is disabled");
|
||||
HUD.jsterm.clearOutput();
|
||||
|
||||
console.log("Hello world!");
|
||||
let controller = top.document.commandDispatcher.
|
||||
getControllerForCommand("cmd_copy");
|
||||
is(controller.isCommandEnabled("cmd_copy"), false, "cmd_copy is disabled");
|
||||
|
||||
outputNode.selectedIndex = 0;
|
||||
outputNode.focus();
|
||||
console.log("Hello world! bug587617");
|
||||
|
||||
goUpdateCommand("cmd_copy");
|
||||
waitForSuccess({
|
||||
name: "console log 'Hello world!' message",
|
||||
validatorFn: function()
|
||||
{
|
||||
return outputNode.textContent.indexOf("bug587617") > -1;
|
||||
},
|
||||
successFn: function()
|
||||
{
|
||||
outputNode.selectedIndex = 0;
|
||||
outputNode.focus();
|
||||
|
||||
controller = top.document.commandDispatcher.
|
||||
getControllerForCommand("cmd_copy");
|
||||
is(controller.isCommandEnabled("cmd_copy"), true, "cmd_copy is enabled");
|
||||
|
||||
let selectedNode = outputNode.getItemAtIndex(0);
|
||||
waitForClipboard(getExpectedClipboardText(selectedNode), clipboardSetup,
|
||||
testContextMenuCopy, testContextMenuCopy);
|
||||
};
|
||||
|
||||
make_selection();
|
||||
goUpdateCommand("cmd_copy");
|
||||
controller = top.document.commandDispatcher.
|
||||
getControllerForCommand("cmd_copy");
|
||||
is(controller.isCommandEnabled("cmd_copy"), true, "cmd_copy is enabled");
|
||||
let selectedNode = outputNode.getItemAtIndex(0);
|
||||
waitForClipboard(getExpectedClipboardText(selectedNode), clipboardSetup,
|
||||
testContextMenuCopy, testContextMenuCopy);
|
||||
},
|
||||
failureFn: finishTest,
|
||||
});
|
||||
}
|
||||
|
||||
// Test that the context menu "Copy" (which has a different code path) works
|
||||
@ -74,7 +78,7 @@ function testContextMenuCopy() {
|
||||
}
|
||||
|
||||
function getExpectedClipboardText(aItem) {
|
||||
return "[" + ConsoleUtils.timestampString(aItem.timestamp) + "] " +
|
||||
return "[" + WebConsoleUtils.l10n.timestampString(aItem.timestamp) + "] " +
|
||||
aItem.clipboardText;
|
||||
}
|
||||
|
||||
|
@ -44,18 +44,16 @@ const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/te
|
||||
|
||||
function test() {
|
||||
addTab(TEST_URI);
|
||||
browser.addEventListener("DOMContentLoaded", testTextNodeInsertion,
|
||||
false);
|
||||
browser.addEventListener("load", function onLoad() {
|
||||
browser.removeEventListener("load", onLoad, true);
|
||||
openConsole(null, testTextNodeInsertion);
|
||||
}, true);
|
||||
}
|
||||
|
||||
// Test for bug 588730: Adding a text node to an existing label element causes
|
||||
// warnings
|
||||
function testTextNodeInsertion() {
|
||||
browser.removeEventListener("DOMContentLoaded", testTextNodeInsertion,
|
||||
false);
|
||||
openConsole();
|
||||
|
||||
let outputNode = HUDService.getHudByWindow(content).outputNode;
|
||||
function testTextNodeInsertion(hud) {
|
||||
let outputNode = hud.outputNode;
|
||||
|
||||
let label = document.createElementNS(
|
||||
"http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul", "label");
|
||||
@ -71,16 +69,13 @@ function testTextNodeInsertion() {
|
||||
}
|
||||
};
|
||||
|
||||
let nsIConsoleServiceClass = Cc["@mozilla.org/consoleservice;1"];
|
||||
let nsIConsoleService =
|
||||
nsIConsoleServiceClass.getService(Ci.nsIConsoleService);
|
||||
nsIConsoleService.registerListener(listener);
|
||||
Services.console.registerListener(listener);
|
||||
|
||||
// This shouldn't fail.
|
||||
label.appendChild(document.createTextNode("foo"));
|
||||
|
||||
executeSoon(function() {
|
||||
nsIConsoleService.unregisterListener(listener);
|
||||
Services.console.unregisterListener(listener);
|
||||
ok(!error, "no error when adding text nodes as children of labels");
|
||||
|
||||
finishTest();
|
||||
|
@ -50,45 +50,27 @@ function test() {
|
||||
browser.addEventListener("load", tab1Loaded, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a log entry exists in the HUD output node.
|
||||
*
|
||||
* @param {Element} aOutputNode the HUD output node.
|
||||
* @param {string} aMatchString the string you want to check if it exists in the
|
||||
* output node.
|
||||
* @param {boolean} [aOnlyVisible=false] find only messages that are visible,
|
||||
* not hidden by the filter.
|
||||
* @param {boolean} [aFailIfFound=false] fail the test if the string is found in
|
||||
* the output node.
|
||||
*/
|
||||
|
||||
function tab1Loaded(aEvent) {
|
||||
browser.removeEventListener(aEvent.type, arguments.callee, true);
|
||||
browser.contentWindow.wrappedJSObject.console.log("FOO");
|
||||
try {
|
||||
openConsole();
|
||||
}
|
||||
catch (ex) {
|
||||
log(ex);
|
||||
log(ex.stack);
|
||||
}
|
||||
|
||||
tab2 = gBrowser.addTab(TEST_DUMMY_URI);
|
||||
gBrowser.selectedTab = tab2;
|
||||
gBrowser.selectedBrowser.addEventListener("load", tab2Loaded, true);
|
||||
browser.removeEventListener(aEvent.type, tab1Loaded, true);
|
||||
content.console.log("FOO");
|
||||
openConsole(null, function() {
|
||||
tab2 = gBrowser.addTab(TEST_DUMMY_URI);
|
||||
gBrowser.selectedTab = tab2;
|
||||
gBrowser.selectedBrowser.addEventListener("load", tab2Loaded, true);
|
||||
});
|
||||
}
|
||||
|
||||
function tab2Loaded(aEvent) {
|
||||
tab2.linkedBrowser.removeEventListener(aEvent.type, arguments.callee, true);
|
||||
tab2.linkedBrowser.removeEventListener(aEvent.type, tab2Loaded, true);
|
||||
|
||||
HUDService.activateHUDForContext(gBrowser.selectedTab);
|
||||
|
||||
tab1.linkedBrowser.addEventListener("load", tab1Reloaded, true);
|
||||
tab1.linkedBrowser.contentWindow.location.reload();
|
||||
openConsole(gBrowser.selectedTab, function() {
|
||||
tab1.linkedBrowser.addEventListener("load", tab1Reloaded, true);
|
||||
tab1.linkedBrowser.contentWindow.location.reload();
|
||||
});
|
||||
}
|
||||
|
||||
function tab1Reloaded(aEvent) {
|
||||
tab1.linkedBrowser.removeEventListener(aEvent.type, arguments.callee, true);
|
||||
tab1.linkedBrowser.removeEventListener(aEvent.type, tab1Reloaded, true);
|
||||
|
||||
let hud1 = HUDService.getHudByWindow(tab1.linkedBrowser.contentWindow);
|
||||
let outputNode1 = hud1.outputNode;
|
||||
@ -105,8 +87,9 @@ function tab1Reloaded(aEvent) {
|
||||
msg = "Didn't find the iframe network request in tab2";
|
||||
testLogEntry(outputNode2, TEST_IFRAME_URI, msg, true, true);
|
||||
|
||||
HUDService.deactivateHUDForContext(tab2);
|
||||
gBrowser.removeTab(tab2);
|
||||
|
||||
finishTest();
|
||||
closeConsole(tab2, function() {
|
||||
gBrowser.removeTab(tab2);
|
||||
tab1 = tab2 = null;
|
||||
executeSoon(finishTest);
|
||||
});
|
||||
}
|
||||
|
@ -28,7 +28,7 @@ function test() {
|
||||
}
|
||||
|
||||
function onWindowLoad(aEvent) {
|
||||
win2.removeEventListener(aEvent.type, arguments.callee, true);
|
||||
win2.removeEventListener(aEvent.type, onWindowLoad, true);
|
||||
|
||||
// Add two tabs in the new window.
|
||||
addTabs(win2);
|
||||
@ -39,48 +39,71 @@ function addTabs(aWindow) {
|
||||
let tab = aWindow.gBrowser.addTab(TEST_URI);
|
||||
openTabs.push(tab);
|
||||
|
||||
tab.linkedBrowser.addEventListener("load", function(aEvent) {
|
||||
tab.linkedBrowser.removeEventListener(aEvent.type, arguments.callee,
|
||||
true);
|
||||
tab.linkedBrowser.addEventListener("load", function onLoad(aEvent) {
|
||||
tab.linkedBrowser.removeEventListener(aEvent.type, onLoad, true);
|
||||
|
||||
loadedTabCount++;
|
||||
if (loadedTabCount >= 4) {
|
||||
executeSoon(performTest);
|
||||
executeSoon(openConsoles);
|
||||
}
|
||||
}, true);
|
||||
}
|
||||
}
|
||||
|
||||
function performTest() {
|
||||
function openConsoles() {
|
||||
// open the Web Console for each of the four tabs and log a message.
|
||||
let consolesOpen = 0;
|
||||
for (let i = 0; i < openTabs.length; i++) {
|
||||
let tab = openTabs[i];
|
||||
HUDService.activateHUDForContext(tab);
|
||||
let hudId = HUDService.getHudIdByWindow(tab.linkedBrowser.contentWindow);
|
||||
ok(hudId, "HUD is open for tab " + i);
|
||||
let HUD = HUDService.hudReferences[hudId];
|
||||
HUD.console.log("message for tab " + i);
|
||||
openConsole(tab, function(index, hud) {
|
||||
ok(hud, "HUD is open for tab " + index);
|
||||
hud.console.log("message for tab " + index);
|
||||
consolesOpen++;
|
||||
}.bind(null, i));
|
||||
}
|
||||
|
||||
let displays = Object.keys(HUDService.hudReferences);
|
||||
is(displays.length, 4, "four displays found");
|
||||
|
||||
win2.close();
|
||||
|
||||
executeSoon(function() {
|
||||
win1.gBrowser.removeTab(openTabs[0]);
|
||||
win1.gBrowser.removeTab(openTabs[1]);
|
||||
|
||||
executeSoon(function() {
|
||||
displays = Object.keys(HUDService.hudReferences);
|
||||
is(displays.length, 0, "no displays found");
|
||||
ok(!HUDService.storage, "no storage found");
|
||||
ok(!HUDService.httpObserver, "no httpObserver found");
|
||||
|
||||
displays = openTabs = win1 = win2 = null;
|
||||
|
||||
finishTest();
|
||||
});
|
||||
waitForSuccess({
|
||||
name: "4 web consoles opened",
|
||||
validatorFn: function()
|
||||
{
|
||||
return consolesOpen == 4;
|
||||
},
|
||||
successFn: closeConsoles,
|
||||
failureFn: closeConsoles,
|
||||
});
|
||||
}
|
||||
|
||||
function closeConsoles() {
|
||||
let consolesClosed = 0;
|
||||
|
||||
function onWebConsoleClose(aSubject, aTopic) {
|
||||
if (aTopic == "web-console-destroyed") {
|
||||
consolesClosed++;
|
||||
}
|
||||
}
|
||||
|
||||
Services.obs.addObserver(onWebConsoleClose, "web-console-destroyed", false);
|
||||
|
||||
win2.close();
|
||||
|
||||
win1.gBrowser.removeTab(openTabs[0]);
|
||||
win1.gBrowser.removeTab(openTabs[1]);
|
||||
|
||||
openTabs = win1 = win2 = null;
|
||||
|
||||
function onTimeout() {
|
||||
Services.obs.removeObserver(onWebConsoleClose, "web-console-destroyed");
|
||||
executeSoon(finishTest);
|
||||
}
|
||||
|
||||
waitForSuccess({
|
||||
name: "4 web consoles closed",
|
||||
validatorFn: function()
|
||||
{
|
||||
return consolesClosed == 4;
|
||||
},
|
||||
successFn: onTimeout,
|
||||
failureFn: onTimeout,
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -89,12 +89,12 @@ const TESTS = [
|
||||
category: "Image",
|
||||
matchString: "corrupt",
|
||||
},
|
||||
/* Disabled until bug 675221 lands.
|
||||
{ // #7
|
||||
{ // #15
|
||||
file: "test-bug-595934-workers.html",
|
||||
category: "Web Worker",
|
||||
matchString: "fooBarWorker",
|
||||
},*/
|
||||
expectError: true,
|
||||
},
|
||||
];
|
||||
|
||||
let pos = -1;
|
||||
@ -103,13 +103,14 @@ let foundCategory = false;
|
||||
let foundText = false;
|
||||
let output = null;
|
||||
let jsterm = null;
|
||||
let testEnded = false;
|
||||
|
||||
let TestObserver = {
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver]),
|
||||
|
||||
observe: function test_observe(aSubject)
|
||||
{
|
||||
if (!(aSubject instanceof Ci.nsIScriptError)) {
|
||||
if (testEnded || !(aSubject instanceof Ci.nsIScriptError)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -125,24 +126,21 @@ let TestObserver = {
|
||||
else {
|
||||
ok(false, aSubject.sourceName + ':' + aSubject.lineNumber + '; ' +
|
||||
aSubject.errorMessage);
|
||||
executeSoon(finish);
|
||||
testEnded = true;
|
||||
executeSoon(finishTest);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
function tabLoad(aEvent) {
|
||||
browser.removeEventListener(aEvent.type, arguments.callee, true);
|
||||
|
||||
openConsole();
|
||||
|
||||
let hudId = HUDService.getHudIdByWindow(content);
|
||||
let hud = HUDService.hudReferences[hudId];
|
||||
function consoleOpened(hud) {
|
||||
output = hud.outputNode;
|
||||
output.addEventListener("DOMNodeInserted", onDOMNodeInserted, false);
|
||||
jsterm = hud.jsterm;
|
||||
|
||||
Services.console.registerListener(TestObserver);
|
||||
|
||||
registerCleanupFunction(testEnd);
|
||||
|
||||
executeSoon(testNext);
|
||||
}
|
||||
|
||||
@ -156,26 +154,30 @@ function testNext() {
|
||||
let test = TESTS[pos];
|
||||
let testLocation = TESTS_PATH + test.file;
|
||||
if (test.onload) {
|
||||
browser.addEventListener("load", function(aEvent) {
|
||||
browser.addEventListener("load", function onLoad(aEvent) {
|
||||
if (content.location.href == testLocation) {
|
||||
browser.removeEventListener(aEvent.type, arguments.callee, true);
|
||||
browser.removeEventListener(aEvent.type, onLoad, true);
|
||||
test.onload(aEvent);
|
||||
}
|
||||
}, true);
|
||||
}
|
||||
|
||||
if (test.expectError) {
|
||||
expectUncaughtException();
|
||||
}
|
||||
|
||||
content.location = testLocation;
|
||||
}
|
||||
else {
|
||||
executeSoon(finish);
|
||||
testEnded = true;
|
||||
executeSoon(finishTest);
|
||||
}
|
||||
}
|
||||
|
||||
function testEnd() {
|
||||
Services.console.unregisterListener(TestObserver);
|
||||
output.removeEventListener("DOMNodeInserted", onDOMNodeInserted, false);
|
||||
output = jsterm = null;
|
||||
finishTest();
|
||||
TestObserver = output = jsterm = null;
|
||||
}
|
||||
|
||||
function onDOMNodeInserted(aEvent) {
|
||||
@ -191,9 +193,10 @@ function onDOMNodeInserted(aEvent) {
|
||||
}
|
||||
|
||||
function test() {
|
||||
registerCleanupFunction(testEnd);
|
||||
|
||||
addTab("data:text/html;charset=utf-8,Web Console test for bug 595934 - message categories coverage.");
|
||||
browser.addEventListener("load", tabLoad, true);
|
||||
browser.addEventListener("load", function onLoad() {
|
||||
browser.removeEventListener("load", onLoad, true);
|
||||
openConsole(null, consoleOpened);
|
||||
}, true);
|
||||
}
|
||||
|
||||
|
@ -21,25 +21,19 @@ function tabLoaded(aEvent) {
|
||||
browser.removeEventListener("load", tabLoaded, true);
|
||||
openConsole();
|
||||
|
||||
browser.addEventListener("load", contentLoaded, true);
|
||||
content.location.reload();
|
||||
}
|
||||
|
||||
function contentLoaded(aEvent) {
|
||||
browser.removeEventListener("load", contentLoaded, true);
|
||||
|
||||
let button = content.document.querySelector("button");
|
||||
expectUncaughtException();
|
||||
EventUtils.sendMouseEvent({ type: "click" }, button, content);
|
||||
executeSoon(buttonClicked);
|
||||
}
|
||||
|
||||
function buttonClicked() {
|
||||
let outputNode = HUDService.getHudByWindow(content).outputNode;
|
||||
|
||||
let msg = "the error from the external script was logged";
|
||||
testLogEntry(outputNode, "bogus", msg);
|
||||
expectUncaughtException();
|
||||
EventUtils.sendMouseEvent({ type: "click" }, button, content);
|
||||
|
||||
finishTest();
|
||||
waitForSuccess({
|
||||
name: "external script error message",
|
||||
validatorFn: function()
|
||||
{
|
||||
return outputNode.textContent.indexOf("bogus is not defined") > -1;
|
||||
},
|
||||
successFn: finishTest,
|
||||
failureFn: finishTest,
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -13,17 +13,17 @@ const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/te
|
||||
let newTabIsOpen = false;
|
||||
|
||||
function tabLoaded(aEvent) {
|
||||
gBrowser.selectedBrowser.removeEventListener(aEvent.type, arguments.callee, true);
|
||||
gBrowser.selectedBrowser.removeEventListener(aEvent.type, tabLoaded, true);
|
||||
|
||||
HUDService.activateHUDForContext(gBrowser.selectedTab);
|
||||
|
||||
gBrowser.selectedBrowser.addEventListener("load", tabReloaded, true);
|
||||
expectUncaughtException();
|
||||
content.location.reload();
|
||||
openConsole(gBrowser.selectedTab, function() {
|
||||
gBrowser.selectedBrowser.addEventListener("load", tabReloaded, true);
|
||||
expectUncaughtException();
|
||||
content.location.reload();
|
||||
});
|
||||
}
|
||||
|
||||
function tabReloaded(aEvent) {
|
||||
gBrowser.selectedBrowser.removeEventListener(aEvent.type, arguments.callee, true);
|
||||
gBrowser.selectedBrowser.removeEventListener(aEvent.type, tabReloaded, true);
|
||||
|
||||
let hudId = HUDService.getHudIdByWindow(content);
|
||||
let HUD = HUDService.hudReferences[hudId];
|
||||
@ -34,26 +34,24 @@ function tabReloaded(aEvent) {
|
||||
|
||||
executeSoon(function() {
|
||||
if (newTabIsOpen) {
|
||||
testEnd();
|
||||
executeSoon(finishTest);
|
||||
return;
|
||||
}
|
||||
|
||||
let newTab = gBrowser.addTab();
|
||||
gBrowser.removeCurrentTab();
|
||||
gBrowser.selectedTab = newTab;
|
||||
closeConsole(gBrowser.selectedTab, function() {
|
||||
gBrowser.removeCurrentTab();
|
||||
|
||||
newTabIsOpen = true;
|
||||
gBrowser.selectedBrowser.addEventListener("load", tabLoaded, true);
|
||||
expectUncaughtException();
|
||||
content.location = TEST_URI;
|
||||
let newTab = gBrowser.addTab();
|
||||
gBrowser.selectedTab = newTab;
|
||||
|
||||
newTabIsOpen = true;
|
||||
gBrowser.selectedBrowser.addEventListener("load", tabLoaded, true);
|
||||
expectUncaughtException();
|
||||
content.location = TEST_URI;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function testEnd() {
|
||||
gBrowser.removeCurrentTab();
|
||||
executeSoon(finishTest);
|
||||
}
|
||||
|
||||
function test() {
|
||||
expectUncaughtException();
|
||||
addTab(TEST_URI);
|
||||
|
@ -92,29 +92,37 @@ let inputValues = [
|
||||
let eventHandlers = [];
|
||||
let popupShown = [];
|
||||
let HUD;
|
||||
let testDriver;
|
||||
|
||||
function tabLoad(aEvent) {
|
||||
browser.removeEventListener(aEvent.type, arguments.callee, true);
|
||||
browser.removeEventListener(aEvent.type, tabLoad, true);
|
||||
|
||||
waitForFocus(function () {
|
||||
openConsole();
|
||||
|
||||
let hudId = HUDService.getHudIdByWindow(content);
|
||||
HUD = HUDService.hudReferences[hudId];
|
||||
|
||||
executeSoon(testNext);
|
||||
openConsole(null, function(aHud) {
|
||||
HUD = aHud;
|
||||
testNext();
|
||||
});
|
||||
}, content);
|
||||
}
|
||||
|
||||
function subtestNext() {
|
||||
testDriver.next();
|
||||
}
|
||||
|
||||
function testNext() {
|
||||
let cpos = ++pos;
|
||||
if (cpos == inputValues.length) {
|
||||
if (popupShown.length == inputValues.length) {
|
||||
executeSoon(testEnd);
|
||||
}
|
||||
pos++;
|
||||
if (pos == inputValues.length) {
|
||||
testEnd();
|
||||
return;
|
||||
}
|
||||
|
||||
testDriver = testGen();
|
||||
testDriver.next();
|
||||
}
|
||||
|
||||
function testGen() {
|
||||
let cpos = pos;
|
||||
|
||||
let showsPropertyPanel = inputValues[cpos][0];
|
||||
let inputValue = inputValues[cpos][1];
|
||||
let expectedOutput = inputValues[cpos][2];
|
||||
@ -129,13 +137,26 @@ function testNext() {
|
||||
|
||||
HUD.jsterm.clearOutput();
|
||||
|
||||
// Test the console.log() output.
|
||||
|
||||
// Ugly but it does the job.
|
||||
with (content) {
|
||||
eval("HUD.console.log(" + consoleTest + ")");
|
||||
}
|
||||
|
||||
let outputItem = HUD.outputNode.
|
||||
querySelector(".hud-log:last-child");
|
||||
waitForSuccess({
|
||||
name: "console.log message for test #" + cpos,
|
||||
validatorFn: function()
|
||||
{
|
||||
return HUD.outputNode.querySelector(".hud-log");
|
||||
},
|
||||
successFn: subtestNext,
|
||||
failureFn: testNext,
|
||||
});
|
||||
|
||||
yield;
|
||||
|
||||
let outputItem = HUD.outputNode.querySelector(".hud-log:last-child");
|
||||
ok(outputItem,
|
||||
"found the window.console output line for inputValues[" + cpos + "]");
|
||||
ok(outputItem.textContent.indexOf(consoleOutput) > -1,
|
||||
@ -143,6 +164,8 @@ function testNext() {
|
||||
|
||||
HUD.jsterm.clearOutput();
|
||||
|
||||
// Test jsterm print() output.
|
||||
|
||||
HUD.jsterm.setInputValue("print(" + inputValue + ")");
|
||||
HUD.jsterm.execute();
|
||||
|
||||
@ -153,6 +176,8 @@ function testNext() {
|
||||
ok(outputItem.textContent.indexOf(printOutput) > -1,
|
||||
"jsterm print() output is correct for inputValues[" + cpos + "]");
|
||||
|
||||
// Test jsterm execution output.
|
||||
|
||||
let eventHandlerID = eventHandlers.length + 1;
|
||||
|
||||
let propertyPanelShown = function(aEvent) {
|
||||
@ -161,7 +186,7 @@ function testNext() {
|
||||
return;
|
||||
}
|
||||
|
||||
document.removeEventListener(aEvent.type, arguments.callee, false);
|
||||
document.removeEventListener(aEvent.type, propertyPanelShown, false);
|
||||
eventHandlers[eventHandlerID] = null;
|
||||
|
||||
ok(showsPropertyPanel,
|
||||
@ -170,8 +195,9 @@ function testNext() {
|
||||
aEvent.target.hidePopup();
|
||||
|
||||
popupShown[cpos] = true;
|
||||
if (popupShown.length == inputValues.length) {
|
||||
executeSoon(testEnd);
|
||||
|
||||
if (showsPropertyPanel) {
|
||||
subtestNext();
|
||||
}
|
||||
};
|
||||
|
||||
@ -192,15 +218,18 @@ function testNext() {
|
||||
let messageBody = outputItem.querySelector(".webconsole-msg-body");
|
||||
ok(messageBody, "we have the message body for inputValues[" + cpos + "]");
|
||||
|
||||
messageBody.addEventListener("click", function(aEvent) {
|
||||
this.removeEventListener(aEvent.type, arguments.callee, false);
|
||||
executeSoon(testNext);
|
||||
}, false);
|
||||
|
||||
// Send the mousedown, mouseup and click events to check if the property
|
||||
// panel opens.
|
||||
EventUtils.sendMouseEvent({ type: "mousedown" }, messageBody, window);
|
||||
EventUtils.sendMouseEvent({ type: "click" }, messageBody, window);
|
||||
|
||||
if (showsPropertyPanel) {
|
||||
yield; // wait for the panel to open if we need to.
|
||||
}
|
||||
|
||||
testNext();
|
||||
|
||||
yield;
|
||||
}
|
||||
|
||||
function testEnd() {
|
||||
@ -222,6 +251,7 @@ function testEnd() {
|
||||
}
|
||||
}
|
||||
|
||||
testDriver = null;
|
||||
executeSoon(finishTest);
|
||||
}
|
||||
|
||||
|
@ -8,13 +8,8 @@
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
function tabLoad(aEvent) {
|
||||
browser.removeEventListener(aEvent.type, arguments.callee, true);
|
||||
|
||||
openConsole();
|
||||
|
||||
let hudId = HUDService.getHudIdByWindow(content);
|
||||
let HUD = HUDService.hudReferences[hudId];
|
||||
function consoleOpened(HUD) {
|
||||
HUD.jsterm.clearOutput();
|
||||
|
||||
let longMessage = "";
|
||||
for (let i = 0; i < 50; i++) {
|
||||
@ -33,7 +28,7 @@ function tabLoad(aEvent) {
|
||||
|
||||
HUD.jsterm.execute("1+1");
|
||||
|
||||
executeSoon(function() {
|
||||
function performTest() {
|
||||
let scrollBox = HUD.outputNode.scrollBoxObject.element;
|
||||
isnot(scrollBox.scrollTop, 0, "scroll location is not at the top");
|
||||
|
||||
@ -54,11 +49,24 @@ function tabLoad(aEvent) {
|
||||
"last message is visible");
|
||||
|
||||
finishTest();
|
||||
};
|
||||
|
||||
waitForSuccess({
|
||||
name: "console output displayed",
|
||||
validatorFn: function()
|
||||
{
|
||||
return HUD.outputNode.itemCount == 103;
|
||||
},
|
||||
successFn: performTest,
|
||||
failureFn: finishTest,
|
||||
});
|
||||
}
|
||||
|
||||
function test() {
|
||||
addTab("data:text/html;charset=utf-8,Web Console test for bug 601352");
|
||||
browser.addEventListener("load", tabLoad, true);
|
||||
browser.addEventListener("load", function tabLoad(aEvent) {
|
||||
browser.removeEventListener(aEvent.type, tabLoad, true);
|
||||
openConsole(null, consoleOpened);
|
||||
}, true);
|
||||
}
|
||||
|
||||
|
@ -16,21 +16,20 @@ function test()
|
||||
addTab("data:text/html;charset=utf-8,Web Console test for bug 602572: log bodies checkbox. tab 1");
|
||||
tabs.push(tab);
|
||||
|
||||
browser.addEventListener("load", function(aEvent) {
|
||||
browser.removeEventListener(aEvent.type, arguments.callee, true);
|
||||
browser.addEventListener("load", function onLoad1(aEvent) {
|
||||
browser.removeEventListener(aEvent.type, onLoad1, true);
|
||||
|
||||
openConsole();
|
||||
openConsole(null, function() {
|
||||
// open tab 2
|
||||
addTab("data:text/html;charset=utf-8,Web Console test for bug 602572: log bodies checkbox. tab 2");
|
||||
tabs.push(tab);
|
||||
|
||||
// open tab 2
|
||||
addTab("data:text/html;charset=utf-8,Web Console test for bug 602572: log bodies checkbox. tab 2");
|
||||
tabs.push(tab);
|
||||
browser.addEventListener("load", function onLoad2(aEvent) {
|
||||
browser.removeEventListener(aEvent.type, onLoad2, true);
|
||||
|
||||
browser.addEventListener("load", function(aEvent) {
|
||||
browser.removeEventListener(aEvent.type, arguments.callee, true);
|
||||
|
||||
openConsole();
|
||||
executeSoon(startTest);
|
||||
}, true);
|
||||
openConsole(null, startTest);
|
||||
}, true);
|
||||
});
|
||||
}, true);
|
||||
}
|
||||
|
||||
@ -52,7 +51,7 @@ function startTest()
|
||||
|
||||
function onpopupshown2(aEvent)
|
||||
{
|
||||
menupopups[1].removeEventListener(aEvent.type, arguments.callee, false);
|
||||
menupopups[1].removeEventListener(aEvent.type, onpopupshown2, false);
|
||||
|
||||
// By default bodies are not logged.
|
||||
isnot(menuitems[1].getAttribute("checked"), "true",
|
||||
@ -63,8 +62,8 @@ function onpopupshown2(aEvent)
|
||||
// Enable body logging.
|
||||
HUDService.saveRequestAndResponseBodies = true;
|
||||
|
||||
menupopups[1].addEventListener("popuphidden", function(aEvent) {
|
||||
menupopups[1].removeEventListener(aEvent.type, arguments.callee, false);
|
||||
menupopups[1].addEventListener("popuphidden", function _onhidden(aEvent) {
|
||||
menupopups[1].removeEventListener(aEvent.type, _onhidden, false);
|
||||
|
||||
// Reopen the context menu.
|
||||
menupopups[1].addEventListener("popupshown", onpopupshown2b, false);
|
||||
@ -75,11 +74,11 @@ function onpopupshown2(aEvent)
|
||||
|
||||
function onpopupshown2b(aEvent)
|
||||
{
|
||||
menupopups[1].removeEventListener(aEvent.type, arguments.callee, false);
|
||||
menupopups[1].removeEventListener(aEvent.type, onpopupshown2b, false);
|
||||
is(menuitems[1].getAttribute("checked"), "true", "menuitems[1] is checked");
|
||||
|
||||
menupopups[1].addEventListener("popuphidden", function(aEvent) {
|
||||
menupopups[1].removeEventListener(aEvent.type, arguments.callee, false);
|
||||
menupopups[1].addEventListener("popuphidden", function _onhidden(aEvent) {
|
||||
menupopups[1].removeEventListener(aEvent.type, _onhidden, false);
|
||||
|
||||
// Switch to tab 1 and open the Web Console context menu from there.
|
||||
gBrowser.selectedTab = tabs[0];
|
||||
@ -102,7 +101,7 @@ function onpopupshown2b(aEvent)
|
||||
|
||||
function onpopupshown1(aEvent)
|
||||
{
|
||||
menupopups[0].removeEventListener(aEvent.type, arguments.callee, false);
|
||||
menupopups[0].removeEventListener(aEvent.type, onpopupshown1, false);
|
||||
|
||||
// The menuitem checkbox must be in sync with the other tabs.
|
||||
is(menuitems[0].getAttribute("checked"), "true", "menuitems[0] is checked");
|
||||
@ -111,8 +110,8 @@ function onpopupshown1(aEvent)
|
||||
HUDService.saveRequestAndResponseBodies = false;
|
||||
|
||||
// Close the menu, and switch back to tab 2.
|
||||
menupopups[0].addEventListener("popuphidden", function(aEvent) {
|
||||
menupopups[0].removeEventListener(aEvent.type, arguments.callee, false);
|
||||
menupopups[0].addEventListener("popuphidden", function _onhidden(aEvent) {
|
||||
menupopups[0].removeEventListener(aEvent.type, _onhidden, false);
|
||||
|
||||
gBrowser.selectedTab = tabs[1];
|
||||
waitForFocus(function() {
|
||||
@ -126,19 +125,20 @@ function onpopupshown1(aEvent)
|
||||
|
||||
function onpopupshown2c(aEvent)
|
||||
{
|
||||
menupopups[1].removeEventListener(aEvent.type, arguments.callee, false);
|
||||
menupopups[1].removeEventListener(aEvent.type, onpopupshown2c, false);
|
||||
|
||||
isnot(menuitems[1].getAttribute("checked"), "true",
|
||||
"menuitems[1] is not checked");
|
||||
|
||||
menupopups[1].addEventListener("popuphidden", function(aEvent) {
|
||||
menupopups[1].removeEventListener(aEvent.type, arguments.callee, false);
|
||||
menupopups[1].addEventListener("popuphidden", function _onhidden(aEvent) {
|
||||
menupopups[1].removeEventListener(aEvent.type, _onhidden, false);
|
||||
|
||||
// Done!
|
||||
huds = menuitems = menupopups = tabs = null;
|
||||
HUDService.deactivateHUDForContext(gBrowser.selectedTab);
|
||||
gBrowser.removeCurrentTab();
|
||||
executeSoon(finishTest);
|
||||
closeConsole(gBrowser.selectedTab, function() {
|
||||
gBrowser.removeCurrentTab();
|
||||
executeSoon(finishTest);
|
||||
});
|
||||
}, false);
|
||||
menupopups[1].hidePopup();
|
||||
}
|
||||
|
@ -39,7 +39,7 @@ let TestObserver = {
|
||||
};
|
||||
|
||||
function tabLoad(aEvent) {
|
||||
browser.removeEventListener(aEvent.type, arguments.callee, true);
|
||||
browser.removeEventListener(aEvent.type, tabLoad, true);
|
||||
|
||||
openConsole();
|
||||
|
||||
@ -52,15 +52,20 @@ function tabLoad(aEvent) {
|
||||
}
|
||||
|
||||
function performTest() {
|
||||
let textContent = hud.outputNode.textContent;
|
||||
isnot(textContent.indexOf("ws://0.0.0.0:81"), -1,
|
||||
"first error message found");
|
||||
isnot(textContent.indexOf("ws://0.0.0.0:82"), -1,
|
||||
"second error message found");
|
||||
|
||||
Services.console.unregisterListener(TestObserver);
|
||||
Services.prefs.setBoolPref(pref_ws, oldPref_ws);
|
||||
finishTest();
|
||||
|
||||
waitForSuccess({
|
||||
name: "websocket error messages displayed",
|
||||
validatorFn: function()
|
||||
{
|
||||
let textContent = hud.outputNode.textContent;
|
||||
return textContent.indexOf("ws://0.0.0.0:81") > -1 &&
|
||||
textContent.indexOf("ws://0.0.0.0:82") > -1;
|
||||
},
|
||||
successFn: finishTest,
|
||||
failureFn: finishTest,
|
||||
});
|
||||
}
|
||||
|
||||
function test() {
|
||||
|
@ -7,29 +7,55 @@ const TEST_URI = 'data:text/html;charset=utf-8,<div style="-moz-opacity:0;">test
|
||||
|
||||
function onContentLoaded()
|
||||
{
|
||||
browser.removeEventListener("load", arguments.callee, true);
|
||||
browser.removeEventListener("load", onContentLoaded, true);
|
||||
|
||||
let HUD = HUDService.getHudByWindow(content);
|
||||
let jsterm = HUD.jsterm;
|
||||
let outputNode = HUD.outputNode;
|
||||
|
||||
let msg = "The unknown CSS property warning is displayed only once";
|
||||
let node = outputNode.firstChild;
|
||||
let cssWarning = "Unknown property '-moz-opacity'. Declaration dropped.";
|
||||
|
||||
is(node.childNodes[2].textContent, "Unknown property '-moz-opacity'. Declaration dropped.", "correct node")
|
||||
is(node.childNodes[3].firstChild.getAttribute("value"), 2, msg);
|
||||
waitForSuccess({
|
||||
name: "2 repeated CSS warnings",
|
||||
validatorFn: function()
|
||||
{
|
||||
return outputNode.textContent.indexOf(cssWarning) > -1;
|
||||
},
|
||||
successFn: function()
|
||||
{
|
||||
let msg = "The unknown CSS property warning is displayed only once";
|
||||
let node = outputNode.firstChild;
|
||||
|
||||
is(node.childNodes[2].textContent, cssWarning, "correct node");
|
||||
is(node.childNodes[3].firstChild.getAttribute("value"), 2, msg);
|
||||
|
||||
testConsoleLogRepeats();
|
||||
},
|
||||
failureFn: finishTest,
|
||||
});
|
||||
}
|
||||
|
||||
function testConsoleLogRepeats()
|
||||
{
|
||||
let HUD = HUDService.getHudByWindow(content);
|
||||
let jsterm = HUD.jsterm;
|
||||
let outputNode = HUD.outputNode;
|
||||
|
||||
jsterm.clearOutput();
|
||||
|
||||
jsterm.setInputValue("for (let i = 0; i < 10; ++i) console.log('this is a line of reasonably long text that I will use to verify that the repeated text node is of an appropriate size.');");
|
||||
jsterm.execute();
|
||||
|
||||
let msg = "The console output is repeated 10 times";
|
||||
let node = outputNode.querySelector(".webconsole-msg-console");
|
||||
is(node.childNodes[3].firstChild.getAttribute("value"), 10, msg);
|
||||
|
||||
jsterm.clearOutput();
|
||||
finishTest();
|
||||
waitForSuccess({
|
||||
name: "10 repeated console.log messages",
|
||||
validatorFn: function()
|
||||
{
|
||||
let node = outputNode.querySelector(".webconsole-msg-console");
|
||||
return node && node.childNodes[3].firstChild.getAttribute("value") == 10;
|
||||
},
|
||||
successFn: finishTest,
|
||||
failureFn: finishTest,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@ -39,14 +65,13 @@ function onContentLoaded()
|
||||
function test()
|
||||
{
|
||||
addTab(TEST_URI);
|
||||
browser.addEventListener("load", function() {
|
||||
browser.removeEventListener("load", arguments.callee, true);
|
||||
|
||||
openConsole();
|
||||
// Clear cached messages that are shown once the Web Console opens.
|
||||
HUDService.getHudByWindow(content).jsterm.clearOutput(true);
|
||||
|
||||
browser.addEventListener("load", onContentLoaded, true);
|
||||
content.location.reload();
|
||||
browser.addEventListener("load", function onLoad() {
|
||||
browser.removeEventListener("load", onLoad, true);
|
||||
openConsole(null, function(aHud) {
|
||||
// Clear cached messages that are shown once the Web Console opens.
|
||||
aHud.jsterm.clearOutput(true);
|
||||
browser.addEventListener("load", onContentLoaded, true);
|
||||
content.location.reload();
|
||||
});
|
||||
}, true);
|
||||
}
|
||||
|
@ -69,6 +69,6 @@ function tabLoaded() {
|
||||
}
|
||||
|
||||
function getExpectedClipboardText(aItem) {
|
||||
return "[" + ConsoleUtils.timestampString(aItem.timestamp) + "] " +
|
||||
return "[" + WebConsoleUtils.l10n.timestampString(aItem.timestamp) + "] " +
|
||||
aItem.clipboardText;
|
||||
}
|
||||
|
@ -7,13 +7,14 @@
|
||||
* Mihai Șucan <mihai.sucan@gmail.com>
|
||||
*/
|
||||
|
||||
function tabLoad(aEvent) {
|
||||
browser.removeEventListener(aEvent.type, arguments.callee, true);
|
||||
let hud, testDriver;
|
||||
|
||||
openConsole();
|
||||
function testNext() {
|
||||
testDriver.next();
|
||||
}
|
||||
|
||||
let hudId = HUDService.getHudIdByWindow(content);
|
||||
let hud = HUDService.hudReferences[hudId];
|
||||
function testGen() {
|
||||
hud.jsterm.clearOutput();
|
||||
let outputNode = hud.outputNode;
|
||||
let scrollBox = outputNode.scrollBoxObject.element;
|
||||
|
||||
@ -21,6 +22,18 @@ function tabLoad(aEvent) {
|
||||
hud.console.log("test message " + i);
|
||||
}
|
||||
|
||||
waitForSuccess({
|
||||
name: "150 console.log messages displayed",
|
||||
validatorFn: function()
|
||||
{
|
||||
return outputNode.querySelectorAll(".hud-log").length == 150;
|
||||
},
|
||||
successFn: testNext,
|
||||
failureFn: finishTest,
|
||||
});
|
||||
|
||||
yield;
|
||||
|
||||
let oldScrollTop = scrollBox.scrollTop;
|
||||
ok(oldScrollTop > 0, "scroll location is not at the top");
|
||||
|
||||
@ -32,30 +45,60 @@ function tabLoad(aEvent) {
|
||||
let topPosition = scrollBox.scrollTop;
|
||||
isnot(topPosition, oldScrollTop, "scroll location updated (moved to top)");
|
||||
|
||||
executeSoon(function() {
|
||||
// add a message and make sure scroll doesn't change
|
||||
hud.console.log("test message 150");
|
||||
// add a message and make sure scroll doesn't change
|
||||
hud.console.log("test message 150");
|
||||
|
||||
is(scrollBox.scrollTop, topPosition, "scroll location is still at the top");
|
||||
|
||||
// scroll back to the bottom
|
||||
outputNode.lastChild.focus();
|
||||
EventUtils.synthesizeKey("VK_END", {});
|
||||
|
||||
executeSoon(function() {
|
||||
oldScrollTop = outputNode.scrollTop;
|
||||
|
||||
hud.console.log("test message 151");
|
||||
|
||||
isnot(scrollBox.scrollTop, oldScrollTop,
|
||||
"scroll location updated (moved to bottom)");
|
||||
|
||||
finishTest();
|
||||
});
|
||||
waitForSuccess({
|
||||
name: "console.log message no. 151 displayed",
|
||||
validatorFn: function()
|
||||
{
|
||||
return outputNode.querySelectorAll(".hud-log").length == 151;
|
||||
},
|
||||
successFn: testNext,
|
||||
failureFn: finishTest,
|
||||
});
|
||||
|
||||
yield;
|
||||
|
||||
is(scrollBox.scrollTop, topPosition, "scroll location is still at the top");
|
||||
|
||||
// scroll back to the bottom
|
||||
outputNode.lastChild.focus();
|
||||
EventUtils.synthesizeKey("VK_END", {});
|
||||
|
||||
oldScrollTop = outputNode.scrollTop;
|
||||
|
||||
hud.console.log("test message 151");
|
||||
|
||||
waitForSuccess({
|
||||
name: "console.log message no. 152 displayed",
|
||||
validatorFn: function()
|
||||
{
|
||||
return outputNode.querySelectorAll(".hud-log").length == 152;
|
||||
},
|
||||
successFn: testNext,
|
||||
failureFn: finishTest,
|
||||
});
|
||||
|
||||
yield;
|
||||
|
||||
isnot(scrollBox.scrollTop, oldScrollTop,
|
||||
"scroll location updated (moved to bottom)");
|
||||
|
||||
hud = testDriver = null;
|
||||
finishTest();
|
||||
|
||||
yield;
|
||||
}
|
||||
|
||||
function test() {
|
||||
addTab("data:text/html;charset=utf-8,Web Console test for bug 613642: remember scroll location");
|
||||
browser.addEventListener("load", tabLoad, true);
|
||||
browser.addEventListener("load", function tabLoad(aEvent) {
|
||||
browser.removeEventListener(aEvent.type, tabLoad, true);
|
||||
openConsole(null, function(aHud) {
|
||||
hud = aHud;
|
||||
testDriver = testGen();
|
||||
testDriver.next();
|
||||
});
|
||||
}, true);
|
||||
}
|
||||
|
@ -7,13 +7,15 @@
|
||||
* Mihai Șucan <mihai.sucan@gmail.com>
|
||||
*/
|
||||
|
||||
function tabLoad(aEvent) {
|
||||
browser.removeEventListener(aEvent.type, arguments.callee, true);
|
||||
let hud, testDriver;
|
||||
|
||||
openConsole();
|
||||
function testNext() {
|
||||
testDriver.next();
|
||||
}
|
||||
|
||||
function testGen() {
|
||||
hud.jsterm.clearOutput();
|
||||
|
||||
let hudId = HUDService.getHudIdByWindow(content);
|
||||
let hud = HUDService.hudReferences[hudId];
|
||||
let outputNode = hud.outputNode;
|
||||
let oldPref = Services.prefs.getIntPref("devtools.hud.loglimit.console");
|
||||
|
||||
@ -25,6 +27,18 @@ function tabLoad(aEvent) {
|
||||
hud.console.log("test message " + i);
|
||||
}
|
||||
|
||||
waitForSuccess({
|
||||
name: "150 console.log messages displayed",
|
||||
validatorFn: function()
|
||||
{
|
||||
return outputNode.querySelectorAll(".hud-log").length == 140;
|
||||
},
|
||||
successFn: testNext,
|
||||
failureFn: finishTest,
|
||||
});
|
||||
|
||||
yield;
|
||||
|
||||
let oldScrollTop = scrollBoxElement.scrollTop;
|
||||
ok(oldScrollTop > 0, "scroll location is not at the top");
|
||||
|
||||
@ -45,6 +59,18 @@ function tabLoad(aEvent) {
|
||||
// add a message
|
||||
hud.console.log("hello world");
|
||||
|
||||
waitForSuccess({
|
||||
name: "console.log message #151 displayed",
|
||||
validatorFn: function()
|
||||
{
|
||||
return outputNode.textContent.indexOf("hello world") > -1;
|
||||
},
|
||||
successFn: testNext,
|
||||
failureFn: finishTest,
|
||||
});
|
||||
|
||||
yield;
|
||||
|
||||
// Scroll location needs to change, because one message is also removed, and
|
||||
// we need to scroll a bit towards the top, to keep the current view in sync.
|
||||
isnot(scrollBoxElement.scrollTop, oldScrollTop,
|
||||
@ -54,10 +80,22 @@ function tabLoad(aEvent) {
|
||||
"first message removed");
|
||||
|
||||
Services.prefs.setIntPref("devtools.hud.loglimit.console", oldPref);
|
||||
|
||||
hud = testDriver = null;
|
||||
finishTest();
|
||||
|
||||
yield;
|
||||
}
|
||||
|
||||
function test() {
|
||||
addTab("data:text/html;charset=utf-8,Web Console test for bug 613642: maintain scroll with pruning of old messages");
|
||||
browser.addEventListener("load", tabLoad, true);
|
||||
browser.addEventListener("load", function tabLoad(aEvent) {
|
||||
browser.removeEventListener(aEvent.type, tabLoad, true);
|
||||
|
||||
openConsole(null, function(aHud) {
|
||||
hud = aHud;
|
||||
testDriver = testGen();
|
||||
testDriver.next();
|
||||
});
|
||||
}, true);
|
||||
}
|
||||
|
@ -7,13 +7,9 @@
|
||||
* Mihai Șucan <mihai.sucan@gmail.com>
|
||||
*/
|
||||
|
||||
function tabLoad(aEvent) {
|
||||
browser.removeEventListener(aEvent.type, arguments.callee, true);
|
||||
function consoleOpened(hud) {
|
||||
hud.jsterm.clearOutput();
|
||||
|
||||
openConsole();
|
||||
|
||||
let hudId = HUDService.getHudIdByWindow(content);
|
||||
let hud = HUDService.hudReferences[hudId];
|
||||
let outputNode = hud.outputNode;
|
||||
let boxObject = outputNode.scrollBoxObject.element;
|
||||
|
||||
@ -21,23 +17,37 @@ function tabLoad(aEvent) {
|
||||
hud.console.log("test message " + i);
|
||||
}
|
||||
|
||||
let oldScrollTop = boxObject.scrollTop;
|
||||
ok(oldScrollTop > 0, "scroll location is not at the top");
|
||||
waitForSuccess({
|
||||
name: "console.log messages displayed",
|
||||
validatorFn: function()
|
||||
{
|
||||
return outputNode.itemCount == 150;
|
||||
},
|
||||
successFn: function()
|
||||
{
|
||||
let oldScrollTop = boxObject.scrollTop;
|
||||
ok(oldScrollTop > 0, "scroll location is not at the top");
|
||||
|
||||
hud.jsterm.execute("'hello world'");
|
||||
hud.jsterm.execute("'hello world'");
|
||||
|
||||
isnot(boxObject.scrollTop, oldScrollTop, "scroll location updated");
|
||||
isnot(boxObject.scrollTop, oldScrollTop, "scroll location updated");
|
||||
|
||||
oldScrollTop = boxObject.scrollTop;
|
||||
outputNode.scrollBoxObject.ensureElementIsVisible(outputNode.lastChild);
|
||||
oldScrollTop = boxObject.scrollTop;
|
||||
outputNode.scrollBoxObject.ensureElementIsVisible(outputNode.lastChild);
|
||||
|
||||
is(boxObject.scrollTop, oldScrollTop, "scroll location is the same");
|
||||
is(boxObject.scrollTop, oldScrollTop, "scroll location is the same");
|
||||
|
||||
finishTest();
|
||||
finishTest();
|
||||
},
|
||||
failureFn: finishTest,
|
||||
});
|
||||
}
|
||||
|
||||
function test() {
|
||||
addTab("data:text/html;charset=utf-8,Web Console test for bug 614793: jsterm result scroll");
|
||||
browser.addEventListener("load", tabLoad, true);
|
||||
browser.addEventListener("load", function onLoad(aEvent) {
|
||||
browser.removeEventListener(aEvent.type, onLoad, true);
|
||||
openConsole(null, consoleOpened);
|
||||
}, true);
|
||||
}
|
||||
|
||||
|
@ -53,57 +53,50 @@ let TestObserver = {
|
||||
|
||||
is(aSubject.category, "content javascript", "error category");
|
||||
|
||||
testEnded = true;
|
||||
if (aSubject.category == "content javascript") {
|
||||
executeSoon(checkOutput);
|
||||
}
|
||||
else {
|
||||
testEnd();
|
||||
executeSoon(finishTest);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
function checkOutput()
|
||||
{
|
||||
if (testEnded) {
|
||||
return;
|
||||
}
|
||||
|
||||
let textContent = hud.outputNode.textContent;
|
||||
isnot(textContent.indexOf("bug618078exception"), -1,
|
||||
"exception message");
|
||||
|
||||
testEnd();
|
||||
waitForSuccess({
|
||||
name: "exception message",
|
||||
validatorFn: function()
|
||||
{
|
||||
return hud.outputNode.textContent.indexOf("bug618078exception") > -1;
|
||||
},
|
||||
successFn: finishTest,
|
||||
failureFn: finishTest,
|
||||
});
|
||||
}
|
||||
|
||||
function testEnd()
|
||||
{
|
||||
if (testEnded) {
|
||||
return;
|
||||
}
|
||||
|
||||
testEnded = true;
|
||||
Services.console.unregisterListener(TestObserver);
|
||||
finishTest();
|
||||
}
|
||||
|
||||
function test()
|
||||
{
|
||||
addTab("data:text/html;charset=utf-8,Web Console test for bug 618078");
|
||||
|
||||
browser.addEventListener("load", function() {
|
||||
browser.removeEventListener("load", arguments.callee, true);
|
||||
browser.addEventListener("load", function onLoad() {
|
||||
browser.removeEventListener("load", onLoad, true);
|
||||
|
||||
openConsole();
|
||||
openConsole(null, function(aHud) {
|
||||
hud = aHud;
|
||||
Services.console.registerListener(TestObserver);
|
||||
registerCleanupFunction(testEnd);
|
||||
|
||||
let hudId = HUDService.getHudIdByWindow(content);
|
||||
hud = HUDService.hudReferences[hudId];
|
||||
|
||||
Services.console.registerListener(TestObserver);
|
||||
registerCleanupFunction(testEnd);
|
||||
|
||||
executeSoon(function() {
|
||||
expectUncaughtException();
|
||||
content.location = TEST_URI;
|
||||
executeSoon(function() {
|
||||
expectUncaughtException();
|
||||
content.location = TEST_URI;
|
||||
});
|
||||
});
|
||||
}, true);
|
||||
}
|
||||
|
@ -44,8 +44,8 @@ let pb = Cc["@mozilla.org/privatebrowsing;1"].
|
||||
function test() {
|
||||
addTab("data:text/html;charset=utf-8,Web Console test for bug 618311 (private browsing)");
|
||||
|
||||
browser.addEventListener("load", function() {
|
||||
browser.removeEventListener("load", arguments.callee, true);
|
||||
browser.addEventListener("load", function onLoad() {
|
||||
browser.removeEventListener("load", onLoad, true);
|
||||
|
||||
registerCleanupFunction(function() {
|
||||
pb.privateBrowsingEnabled = false;
|
||||
@ -57,9 +57,10 @@ function test() {
|
||||
togglePBAndThen(function() {
|
||||
ok(pb.privateBrowsingEnabled, "private browsing is enabled");
|
||||
|
||||
HUDService.activateHUDForContext(gBrowser.selectedTab);
|
||||
content.location = TEST_URI;
|
||||
gBrowser.selectedBrowser.addEventListener("load", tabLoaded, true);
|
||||
openConsole(gBrowser.selectedTab, function() {
|
||||
content.location = TEST_URI;
|
||||
gBrowser.selectedBrowser.addEventListener("load", tabLoaded, true);
|
||||
});
|
||||
});
|
||||
}, true);
|
||||
}
|
||||
@ -128,6 +129,7 @@ function tabLoaded() {
|
||||
|
||||
ok(!pb.privateBrowsingEnabled, "private browsing is not enabled");
|
||||
|
||||
gBrowser.removeCurrentTab();
|
||||
executeSoon(finishTest);
|
||||
});
|
||||
}
|
||||
|
@ -10,14 +10,9 @@
|
||||
const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/test-bug-621644-jsterm-dollar.html";
|
||||
|
||||
function tabLoad(aEvent) {
|
||||
browser.removeEventListener(aEvent.type, arguments.callee, true);
|
||||
|
||||
waitForFocus(function () {
|
||||
openConsole();
|
||||
|
||||
let hudId = HUDService.getHudIdByWindow(content);
|
||||
let HUD = HUDService.hudReferences[hudId];
|
||||
browser.removeEventListener(aEvent.type, tabLoad, true);
|
||||
|
||||
openConsole(null, function(HUD) {
|
||||
HUD.jsterm.clearOutput();
|
||||
|
||||
HUD.jsterm.setInputValue("$(document.body)");
|
||||
@ -39,7 +34,7 @@ function tabLoad(aEvent) {
|
||||
"jsterm output is correct for $$()");
|
||||
|
||||
executeSoon(finishTest);
|
||||
}, content);
|
||||
});
|
||||
}
|
||||
|
||||
function test() {
|
||||
|
@ -1,37 +1,45 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
let itemsSet, HUD;
|
||||
let itemsSet, HUD, outputNode;
|
||||
|
||||
function test() {
|
||||
addTab("data:text/html;charset=utf-8,Web Console test for bug 626484");
|
||||
browser.addEventListener("load", tabLoaded, true);
|
||||
browser.addEventListener("load", function tabLoaded(aEvent) {
|
||||
browser.removeEventListener(aEvent.type, tabLoaded, true);
|
||||
openConsole(null, consoleOpened);
|
||||
}, true);
|
||||
}
|
||||
|
||||
function tabLoaded(aEvent) {
|
||||
browser.removeEventListener(aEvent.type, arguments.callee, true);
|
||||
openConsole();
|
||||
|
||||
let console = browser.contentWindow.wrappedJSObject.console;
|
||||
function consoleOpened(aHud) {
|
||||
HUD = aHud;
|
||||
outputNode = HUD.outputNode;
|
||||
HUD.jsterm.clearOutput();
|
||||
|
||||
let console = content.wrappedJSObject.console;
|
||||
console.log("The first line.");
|
||||
console.log("The second line.");
|
||||
console.log("The last line.");
|
||||
|
||||
let hudId = HUDService.getHudIdByWindow(content);
|
||||
HUD = HUDService.hudReferences[hudId];
|
||||
outputNode = HUD.outputNode;
|
||||
|
||||
itemsSet = [[0, 1, 2], [0, 2, 1], [1, 0, 2], [1, 2, 0], [2, 0, 1],
|
||||
[2, 1, 0]];
|
||||
|
||||
nextTest();
|
||||
waitForSuccess({
|
||||
name: "console.log messages displayed",
|
||||
validatorFn: function()
|
||||
{
|
||||
return outputNode.querySelectorAll(".hud-log").length == 3;
|
||||
},
|
||||
successFn: nextTest,
|
||||
failureFn: finishTest,
|
||||
});
|
||||
}
|
||||
|
||||
function nextTest() {
|
||||
if (itemsSet.length === 0) {
|
||||
outputNode.clearSelection();
|
||||
HUD.jsterm.clearOutput();
|
||||
HUD = null;
|
||||
finish();
|
||||
HUD = outputNode = null;
|
||||
executeSoon(finishTest);
|
||||
}
|
||||
else {
|
||||
outputNode.clearSelection();
|
||||
@ -50,7 +58,7 @@ function getExpectedClipboardText(aItemCount) {
|
||||
for (let i = 0; i < aItemCount; i++) {
|
||||
let item = outputNode.getItemAtIndex(i);
|
||||
expectedClipboardText.push("[" +
|
||||
ConsoleUtils.timestampString(item.timestamp) + "] " +
|
||||
WebConsoleUtils.l10n.timestampString(item.timestamp) + "] " +
|
||||
item.clipboardText);
|
||||
}
|
||||
return expectedClipboardText.join("\n");
|
||||
|
@ -45,6 +45,11 @@ function test() {
|
||||
|
||||
function tabLoaded() {
|
||||
browser.removeEventListener("load", tabLoaded, true);
|
||||
|
||||
let tmp = {};
|
||||
Cu.import("resource:///modules/WebConsoleUtils.jsm", tmp);
|
||||
let WCU = tmp.WebConsoleUtils;
|
||||
|
||||
openConsole();
|
||||
|
||||
let hudId = HUDService.getHudIdByWindow(content);
|
||||
@ -57,7 +62,7 @@ function tabLoaded() {
|
||||
let result = win.gen1.next();
|
||||
let completion = jsterm.propertyProvider(win, "gen1.");
|
||||
is(completion, null, "no matchees for gen1");
|
||||
ok(!jsterm.isResultInspectable(win.gen1),
|
||||
ok(!WCU.isObjectInspectable(win.gen1),
|
||||
"gen1 is not inspectable");
|
||||
|
||||
is(result+1, win.gen1.next(), "gen1.next() did not execute");
|
||||
@ -66,7 +71,7 @@ function tabLoaded() {
|
||||
|
||||
completion = jsterm.propertyProvider(win, "gen2.");
|
||||
is(completion, null, "no matchees for gen2");
|
||||
ok(!jsterm.isResultInspectable(win.gen2),
|
||||
ok(!WCU.isObjectInspectable(win.gen2),
|
||||
"gen2 is not inspectable");
|
||||
|
||||
is((result/2+1)*2, win.gen2.next(),
|
||||
@ -78,7 +83,7 @@ function tabLoaded() {
|
||||
|
||||
completion = jsterm.propertyProvider(win, "iter1.");
|
||||
is(completion, null, "no matchees for iter1");
|
||||
ok(!jsterm.isResultInspectable(win.iter1),
|
||||
ok(!WCU.isObjectInspectable(win.iter1),
|
||||
"iter1 is not inspectable");
|
||||
|
||||
result = win.iter1.next();
|
||||
@ -87,13 +92,13 @@ function tabLoaded() {
|
||||
|
||||
completion = jsterm.propertyProvider(content, "iter2.");
|
||||
is(completion, null, "no matchees for iter2");
|
||||
ok(!jsterm.isResultInspectable(win.iter2),
|
||||
ok(!WCU.isObjectInspectable(win.iter2),
|
||||
"iter2 is not inspectable");
|
||||
|
||||
completion = jsterm.propertyProvider(win, "window.");
|
||||
ok(completion, "matches available for window");
|
||||
ok(completion.matches.length, "matches available for window (length)");
|
||||
ok(jsterm.isResultInspectable(win),
|
||||
ok(WCU.isObjectInspectable(win),
|
||||
"window is inspectable");
|
||||
|
||||
let panel = jsterm.openPropertyPanel("Test", win);
|
||||
|
@ -10,7 +10,7 @@
|
||||
const TEST_URI = "http://example.com/browser/browser/devtools/" +
|
||||
"webconsole/test/test-bug-644419-log-limits.html";
|
||||
|
||||
var gOldPref, gHudId;
|
||||
var gOldPref;
|
||||
|
||||
function test() {
|
||||
addTab("data:text/html;charset=utf-8,Web Console test for bug 644419: Console should " +
|
||||
@ -19,53 +19,82 @@ function test() {
|
||||
}
|
||||
|
||||
function onLoad(aEvent) {
|
||||
browser.removeEventListener(aEvent.type, arguments.callee, true);
|
||||
browser.removeEventListener(aEvent.type, onLoad, true);
|
||||
|
||||
openConsole();
|
||||
openConsole(null, function(aHud) {
|
||||
aHud.jsterm.clearOutput();
|
||||
hud = aHud;
|
||||
outputNode = aHud.outputNode;
|
||||
|
||||
gHudId = HUDService.getHudIdByWindow(content);
|
||||
browser.addEventListener("load", testWebDevLimits, true);
|
||||
expectUncaughtException();
|
||||
content.location = TEST_URI;
|
||||
}
|
||||
|
||||
function testWebDevLimits(aEvent) {
|
||||
browser.removeEventListener(aEvent.type, arguments.callee, true);
|
||||
gOldPref = Services.prefs.getIntPref("devtools.hud.loglimit.console");
|
||||
Services.prefs.setIntPref("devtools.hud.loglimit.console", 10);
|
||||
|
||||
let hud = HUDService.hudReferences[gHudId];
|
||||
outputNode = hud.outputNode;
|
||||
|
||||
executeSoon(function() {
|
||||
// Find the sentinel entry.
|
||||
findLogEntry("bar is not defined");
|
||||
|
||||
// Fill the log with Web Developer errors.
|
||||
for (let i = 0; i < 11; i++) {
|
||||
hud.console.log("test message " + i);
|
||||
}
|
||||
testLogEntry(outputNode, "test message 0", "first message is pruned", false, true);
|
||||
findLogEntry("test message 1");
|
||||
// Check if the sentinel entry is still there.
|
||||
findLogEntry("bar is not defined");
|
||||
|
||||
Services.prefs.setIntPref("devtools.hud.loglimit.console", gOldPref);
|
||||
testJsLimits();
|
||||
browser.addEventListener("load", testWebDevLimits, true);
|
||||
expectUncaughtException();
|
||||
content.location = TEST_URI;
|
||||
});
|
||||
}
|
||||
|
||||
function testJsLimits(aEvent) {
|
||||
function testWebDevLimits(aEvent) {
|
||||
browser.removeEventListener(aEvent.type, testWebDevLimits, true);
|
||||
gOldPref = Services.prefs.getIntPref("devtools.hud.loglimit.console");
|
||||
Services.prefs.setIntPref("devtools.hud.loglimit.console", 10);
|
||||
|
||||
// Find the sentinel entry.
|
||||
waitForSuccess({
|
||||
name: "bar is not defined",
|
||||
validatorFn: function()
|
||||
{
|
||||
return outputNode.textContent.indexOf("bar is not defined") > -1;
|
||||
},
|
||||
successFn: testWebDevLimits2,
|
||||
failureFn: testWebDevLimits2,
|
||||
});
|
||||
}
|
||||
|
||||
function testWebDevLimits2() {
|
||||
// Fill the log with Web Developer errors.
|
||||
for (let i = 0; i < 11; i++) {
|
||||
hud.console.log("test message " + i);
|
||||
}
|
||||
|
||||
waitForSuccess({
|
||||
name: "11 console.log messages displayed",
|
||||
validatorFn: function()
|
||||
{
|
||||
return outputNode.textContent.indexOf("test message 10") > -1;
|
||||
},
|
||||
successFn: function()
|
||||
{
|
||||
testLogEntry(outputNode, "test message 0", "first message is pruned", false, true);
|
||||
findLogEntry("test message 1");
|
||||
// Check if the sentinel entry is still there.
|
||||
findLogEntry("bar is not defined");
|
||||
|
||||
Services.prefs.setIntPref("devtools.hud.loglimit.console", gOldPref);
|
||||
testJsLimits();
|
||||
},
|
||||
failureFn: testJsLimits,
|
||||
});
|
||||
}
|
||||
|
||||
function testJsLimits() {
|
||||
gOldPref = Services.prefs.getIntPref("devtools.hud.loglimit.exception");
|
||||
Services.prefs.setIntPref("devtools.hud.loglimit.exception", 10);
|
||||
|
||||
let hud = HUDService.hudReferences[gHudId];
|
||||
hud.jsterm.clearOutput();
|
||||
outputNode = hud.outputNode;
|
||||
hud.console.log("testing JS limits");
|
||||
|
||||
// Find the sentinel entry.
|
||||
findLogEntry("testing JS limits");
|
||||
waitForSuccess({
|
||||
name: "console.log 'testing JS limits'",
|
||||
validatorFn: function()
|
||||
{
|
||||
return outputNode.textContent.indexOf("testing JS limits") > -1;
|
||||
},
|
||||
successFn: testJsLimits2,
|
||||
failureFn: testNetLimits,
|
||||
});
|
||||
}
|
||||
|
||||
function testJsLimits2() {
|
||||
// Fill the log with JS errors.
|
||||
let head = content.document.getElementsByTagName("head")[0];
|
||||
for (let i = 0; i < 11; i++) {
|
||||
@ -75,33 +104,50 @@ function testJsLimits(aEvent) {
|
||||
head.insertBefore(script, head.firstChild);
|
||||
}
|
||||
|
||||
executeSoon(function() {
|
||||
testLogEntry(outputNode, "fubar0 is not defined", "first message is pruned", false, true);
|
||||
findLogEntry("fubar1 is not defined");
|
||||
// Check if the sentinel entry is still there.
|
||||
findLogEntry("testing JS limits");
|
||||
waitForSuccess({
|
||||
name: "10 JS errors shown",
|
||||
validatorFn: function()
|
||||
{
|
||||
return outputNode.textContent.indexOf("fubar10 is not defined") > -1;
|
||||
},
|
||||
successFn: function()
|
||||
{
|
||||
testLogEntry(outputNode, "fubar0 is not defined", "first message is pruned", false, true);
|
||||
findLogEntry("fubar1 is not defined");
|
||||
// Check if the sentinel entry is still there.
|
||||
findLogEntry("testing JS limits");
|
||||
|
||||
Services.prefs.setIntPref("devtools.hud.loglimit.exception", gOldPref);
|
||||
testNetLimits();
|
||||
Services.prefs.setIntPref("devtools.hud.loglimit.exception", gOldPref);
|
||||
testNetLimits();
|
||||
},
|
||||
failureFn: testNetLimits,
|
||||
});
|
||||
}
|
||||
|
||||
var gCounter, gImage;
|
||||
|
||||
function testNetLimits(aEvent) {
|
||||
function testNetLimits() {
|
||||
gOldPref = Services.prefs.getIntPref("devtools.hud.loglimit.network");
|
||||
Services.prefs.setIntPref("devtools.hud.loglimit.network", 10);
|
||||
|
||||
let hud = HUDService.hudReferences[gHudId];
|
||||
hud.jsterm.clearOutput();
|
||||
outputNode = hud.outputNode;
|
||||
hud.console.log("testing Net limits");
|
||||
|
||||
// Find the sentinel entry.
|
||||
findLogEntry("testing Net limits");
|
||||
// Fill the log with network messages.
|
||||
gCounter = 0;
|
||||
loadImage();
|
||||
waitForSuccess({
|
||||
name: "console.log 'testing Net limits'",
|
||||
validatorFn: function()
|
||||
{
|
||||
return outputNode.textContent.indexOf("testing Net limits") > -1;
|
||||
},
|
||||
successFn: function()
|
||||
{
|
||||
// Fill the log with network messages.
|
||||
gCounter = 0;
|
||||
loadImage();
|
||||
},
|
||||
failureFn: testCssLimits,
|
||||
});
|
||||
}
|
||||
|
||||
function loadImage() {
|
||||
@ -125,18 +171,26 @@ function loadImage() {
|
||||
testCssLimits();
|
||||
}
|
||||
|
||||
function testCssLimits(aEvent) {
|
||||
function testCssLimits() {
|
||||
gOldPref = Services.prefs.getIntPref("devtools.hud.loglimit.cssparser");
|
||||
Services.prefs.setIntPref("devtools.hud.loglimit.cssparser", 10);
|
||||
|
||||
let hud = HUDService.hudReferences[gHudId];
|
||||
hud.jsterm.clearOutput();
|
||||
outputNode = hud.outputNode;
|
||||
hud.console.log("testing CSS limits");
|
||||
|
||||
// Find the sentinel entry.
|
||||
findLogEntry("testing CSS limits");
|
||||
waitForSuccess({
|
||||
name: "console.log 'testing CSS limits'",
|
||||
validatorFn: function()
|
||||
{
|
||||
return outputNode.textContent.indexOf("testing CSS limits") > -1;
|
||||
},
|
||||
successFn: testCssLimits2,
|
||||
failureFn: finishTest,
|
||||
});
|
||||
}
|
||||
|
||||
function testCssLimits2() {
|
||||
// Fill the log with CSS errors.
|
||||
let body = content.document.getElementsByTagName("body")[0];
|
||||
for (let i = 0; i < 11; i++) {
|
||||
@ -144,13 +198,24 @@ function testCssLimits(aEvent) {
|
||||
div.setAttribute("style", "-moz-foobar" + i + ": 42;");
|
||||
body.insertBefore(div, body.firstChild);
|
||||
}
|
||||
executeSoon(function() {
|
||||
testLogEntry(outputNode, "Unknown property '-moz-foobar0'", "first message is pruned", false, true);
|
||||
findLogEntry("Unknown property '-moz-foobar1'");
|
||||
// Check if the sentinel entry is still there.
|
||||
findLogEntry("testing CSS limits");
|
||||
|
||||
Services.prefs.setIntPref("devtools.hud.loglimit.cssparser", gOldPref);
|
||||
finishTest();
|
||||
waitForSuccess({
|
||||
name: "10 CSS errors shown",
|
||||
validatorFn: function()
|
||||
{
|
||||
return outputNode.textContent.indexOf("-moz-foobar10") > -1;
|
||||
},
|
||||
successFn: function()
|
||||
{
|
||||
testLogEntry(outputNode, "Unknown property '-moz-foobar0'",
|
||||
"first message is pruned", false, true);
|
||||
findLogEntry("Unknown property '-moz-foobar1'");
|
||||
// Check if the sentinel entry is still there.
|
||||
findLogEntry("testing CSS limits");
|
||||
|
||||
Services.prefs.setIntPref("devtools.hud.loglimit.cssparser", gOldPref);
|
||||
finishTest();
|
||||
},
|
||||
failureFn: finishTest,
|
||||
});
|
||||
}
|
||||
|
@ -97,7 +97,7 @@ function runSelectionTests()
|
||||
});
|
||||
}
|
||||
|
||||
function performTestComparisons(evt)
|
||||
function performTestComparisons()
|
||||
{
|
||||
InspectorUI.highlighter.removeListener("nodeselected", performTestComparisons);
|
||||
|
||||
@ -105,9 +105,11 @@ function performTestComparisons(evt)
|
||||
is(InspectorUI.highlighter.node, h1, "node selected");
|
||||
is(InspectorUI.selection, h1, "selection matches node");
|
||||
|
||||
HUDService.activateHUDForContext(gBrowser.selectedTab);
|
||||
let hudId = HUDService.getHudIdByWindow(content);
|
||||
let hud = HUDService.hudReferences[hudId];
|
||||
openConsole(gBrowser.selectedTab, performWebConsoleTests);
|
||||
}
|
||||
|
||||
function performWebConsoleTests(hud)
|
||||
{
|
||||
let jsterm = hud.jsterm;
|
||||
outputNode = hud.outputNode;
|
||||
|
||||
@ -127,8 +129,7 @@ function performTestComparisons(evt)
|
||||
|
||||
function finishUp() {
|
||||
InspectorUI.closeInspectorUI();
|
||||
gBrowser.removeCurrentTab();
|
||||
finish();
|
||||
finishTest();
|
||||
}
|
||||
|
||||
function test()
|
||||
|
@ -9,15 +9,13 @@
|
||||
function test() {
|
||||
addTab("http://example.com/browser/browser/devtools/webconsole/" +
|
||||
"test/test-bug-658368-time-methods.html");
|
||||
openConsole();
|
||||
browser.addEventListener("load", onLoad, true);
|
||||
browser.addEventListener("load", function onLoad() {
|
||||
browser.removeEventListener("load", onLoad, true);
|
||||
openConsole(null, consoleOpened);
|
||||
}, true);
|
||||
}
|
||||
|
||||
function onLoad(aEvent) {
|
||||
browser.removeEventListener(aEvent.type, onLoad, true);
|
||||
|
||||
let hudId = HUDService.getHudIdByWindow(content);
|
||||
let hud = HUDService.hudReferences[hudId];
|
||||
function consoleOpened(hud) {
|
||||
outputNode = hud.outputNode;
|
||||
|
||||
executeSoon(function() {
|
||||
@ -28,16 +26,14 @@ function onLoad(aEvent) {
|
||||
// tabs, do not contain the same value.
|
||||
addTab("data:text/html;charset=utf-8,<script type='text/javascript'>" +
|
||||
"console.timeEnd('bTimer');</script>");
|
||||
openConsole();
|
||||
browser.addEventListener("load", testTimerIndependenceInTabs, true);
|
||||
browser.addEventListener("load", function onLoad() {
|
||||
browser.removeEventListener("load", onLoad, true);
|
||||
openConsole(null, testTimerIndependenceInTabs);
|
||||
}, true);
|
||||
});
|
||||
}
|
||||
|
||||
function testTimerIndependenceInTabs(aEvent) {
|
||||
browser.removeEventListener(aEvent.type, testTimerIndependenceInTabs, true);
|
||||
|
||||
let hudId = HUDService.getHudIdByWindow(content);
|
||||
let hud = HUDService.hudReferences[hudId];
|
||||
function testTimerIndependenceInTabs(hud) {
|
||||
outputNode = hud.outputNode;
|
||||
|
||||
executeSoon(function() {
|
||||
@ -46,15 +42,16 @@ function testTimerIndependenceInTabs(aEvent) {
|
||||
|
||||
// The next test makes sure that timers with the same name but in separate
|
||||
// pages, do not contain the same value.
|
||||
browser.addEventListener("load", testTimerIndependenceInSameTab, true);
|
||||
browser.addEventListener("load", function onLoad() {
|
||||
browser.removeEventListener("load", onLoad, true);
|
||||
executeSoon(testTimerIndependenceInSameTab);
|
||||
}, true);
|
||||
content.location = "data:text/html;charset=utf-8,<script type='text/javascript'>" +
|
||||
"console.time('bTimer');</script>";
|
||||
});
|
||||
}
|
||||
|
||||
function testTimerIndependenceInSameTab(aEvent) {
|
||||
browser.removeEventListener(aEvent.type, testTimerIndependenceInSameTab, true);
|
||||
|
||||
function testTimerIndependenceInSameTab() {
|
||||
let hudId = HUDService.getHudIdByWindow(content);
|
||||
let hud = HUDService.hudReferences[hudId];
|
||||
outputNode = hud.outputNode;
|
||||
@ -65,15 +62,16 @@ function testTimerIndependenceInSameTab(aEvent) {
|
||||
|
||||
// Now the following console.timeEnd() call shouldn't display anything,
|
||||
// if the timers in different pages are not related.
|
||||
browser.addEventListener("load", testTimerIndependenceInSameTabAgain, true);
|
||||
browser.addEventListener("load", function onLoad() {
|
||||
browser.removeEventListener("load", onLoad, true);
|
||||
executeSoon(testTimerIndependenceInSameTabAgain);
|
||||
}, true);
|
||||
content.location = "data:text/html;charset=utf-8,<script type='text/javascript'>" +
|
||||
"console.timeEnd('bTimer');</script>";
|
||||
});
|
||||
}
|
||||
|
||||
function testTimerIndependenceInSameTabAgain(aEvent) {
|
||||
browser.removeEventListener(aEvent.type, testTimerIndependenceInSameTabAgain, true);
|
||||
|
||||
function testTimerIndependenceInSameTabAgain(hud) {
|
||||
let hudId = HUDService.getHudIdByWindow(content);
|
||||
let hud = HUDService.hudReferences[hudId];
|
||||
outputNode = hud.outputNode;
|
||||
@ -82,6 +80,9 @@ function testTimerIndependenceInSameTabAgain(aEvent) {
|
||||
testLogEntry(outputNode, "bTimer: timer started", "bTimer was not started",
|
||||
false, true);
|
||||
|
||||
finishTest();
|
||||
closeConsole(gBrowser.selectedTab, function() {
|
||||
gBrowser.removeCurrentTab();
|
||||
executeSoon(finishTest);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@ -9,37 +9,48 @@
|
||||
function test() {
|
||||
addTab("data:text/html;charset=utf-8,Web Console test for bug 659907: Expand console " +
|
||||
"object with a dir method");
|
||||
browser.addEventListener("load", onLoad, true);
|
||||
browser.addEventListener("load", function onLoad(aEvent) {
|
||||
browser.removeEventListener(aEvent.type, onLoad, true);
|
||||
openConsole(null, consoleOpened);
|
||||
}, true);
|
||||
}
|
||||
|
||||
function onLoad(aEvent) {
|
||||
browser.removeEventListener(aEvent.type, arguments.callee, true);
|
||||
|
||||
openConsole();
|
||||
let hudId = HUDService.getHudIdByWindow(content);
|
||||
let hud = HUDService.hudReferences[hudId];
|
||||
function consoleOpened(hud) {
|
||||
outputNode = hud.outputNode;
|
||||
content.console.dir(content.document);
|
||||
findLogEntry("[object HTMLDocument");
|
||||
waitForSuccess({
|
||||
name: "console.dir displayed",
|
||||
validatorFn: function()
|
||||
{
|
||||
return outputNode.textContent.indexOf("[object HTMLDocument") > -1;
|
||||
},
|
||||
successFn: testConsoleDir.bind(null, outputNode),
|
||||
failureFn: finishTest,
|
||||
});
|
||||
}
|
||||
|
||||
function testConsoleDir(outputNode) {
|
||||
let msg = outputNode.querySelectorAll(".webconsole-msg-inspector");
|
||||
is(msg.length, 1, "one message node displayed");
|
||||
let rows = msg[0].propertyTreeView._rows;
|
||||
let view = msg[0].propertyTreeView;
|
||||
let foundQSA = false;
|
||||
let foundLocation = false;
|
||||
let foundWrite = false;
|
||||
for (let i = 0; i < rows.length; i++) {
|
||||
if (rows[i].display == "querySelectorAll: function querySelectorAll()") {
|
||||
for (let i = 0; i < view.rowCount; i++) {
|
||||
let text = view.getCellText(i);
|
||||
if (text == "querySelectorAll: function querySelectorAll()") {
|
||||
foundQSA = true;
|
||||
}
|
||||
else if (rows[i].display == "location: Object") {
|
||||
else if (text == "location: Object") {
|
||||
foundLocation = true;
|
||||
}
|
||||
else if (rows[i].display == "write: function write()") {
|
||||
else if (text == "write: function write()") {
|
||||
foundWrite = true;
|
||||
}
|
||||
}
|
||||
ok(foundQSA, "found document.querySelectorAll");
|
||||
ok(foundLocation, "found document.location");
|
||||
ok(foundWrite, "found document.write");
|
||||
finishTest();
|
||||
msg = view = outputNode = null;
|
||||
executeSoon(finishTest);
|
||||
}
|
||||
|
@ -7,50 +7,127 @@
|
||||
// Tests that console.group/groupEnd works as intended.
|
||||
const GROUP_INDENT = 12;
|
||||
|
||||
let testDriver, hud;
|
||||
|
||||
function test() {
|
||||
addTab("data:text/html;charset=utf-8,Web Console test for bug 664131: Expand console " +
|
||||
"object with group methods");
|
||||
browser.addEventListener("load", onLoad, true);
|
||||
browser.addEventListener("load", function onLoad(aEvent) {
|
||||
browser.removeEventListener(aEvent.type, onLoad, true);
|
||||
openConsole(null, function(aHud) {
|
||||
hud = aHud;
|
||||
testDriver = testGen();
|
||||
testNext();
|
||||
});
|
||||
}, true);
|
||||
}
|
||||
|
||||
function onLoad(aEvent) {
|
||||
browser.removeEventListener(aEvent.type, arguments.callee, true);
|
||||
function testNext() {
|
||||
testDriver.next();
|
||||
}
|
||||
|
||||
openConsole();
|
||||
let hudId = HUDService.getHudIdByWindow(content);
|
||||
let hud = HUDService.hudReferences[hudId];
|
||||
function testGen() {
|
||||
outputNode = hud.outputNode;
|
||||
|
||||
content.console.group("a");
|
||||
findLogEntry("a");
|
||||
hud.jsterm.clearOutput();
|
||||
|
||||
content.console.group("bug664131a");
|
||||
|
||||
waitForSuccess({
|
||||
name: "console.group displayed",
|
||||
validatorFn: function()
|
||||
{
|
||||
return outputNode.textContent.indexOf("bug664131a") > -1;
|
||||
},
|
||||
successFn: testNext,
|
||||
failureFn: finishTest,
|
||||
});
|
||||
|
||||
yield;
|
||||
|
||||
let msg = outputNode.querySelectorAll(".webconsole-msg-icon-container");
|
||||
is(msg.length, 1, "one message node displayed");
|
||||
is(msg[0].style.marginLeft, GROUP_INDENT + "px", "correct group indent found");
|
||||
content.console.log("inside");
|
||||
findLogEntry("inside");
|
||||
let msg = outputNode.querySelectorAll(".webconsole-msg-icon-container");
|
||||
|
||||
content.console.log("bug664131a-inside");
|
||||
|
||||
waitForSuccess({
|
||||
name: "console.log message displayed",
|
||||
validatorFn: function()
|
||||
{
|
||||
return outputNode.textContent.indexOf("bug664131a-inside") > -1;
|
||||
},
|
||||
successFn: testNext,
|
||||
failureFn: finishTest,
|
||||
});
|
||||
|
||||
yield;
|
||||
|
||||
msg = outputNode.querySelectorAll(".webconsole-msg-icon-container");
|
||||
is(msg.length, 2, "two message nodes displayed");
|
||||
is(msg[1].style.marginLeft, GROUP_INDENT + "px", "correct group indent found");
|
||||
content.console.groupEnd("a");
|
||||
content.console.log("outside");
|
||||
findLogEntry("outside");
|
||||
let msg = outputNode.querySelectorAll(".webconsole-msg-icon-container");
|
||||
|
||||
content.console.groupEnd("bug664131a");
|
||||
content.console.log("bug664131-outside");
|
||||
|
||||
waitForSuccess({
|
||||
name: "console.log message displayed after groupEnd()",
|
||||
validatorFn: function()
|
||||
{
|
||||
return outputNode.textContent.indexOf("bug664131-outside") > -1;
|
||||
},
|
||||
successFn: testNext,
|
||||
failureFn: finishTest,
|
||||
});
|
||||
|
||||
yield;
|
||||
|
||||
msg = outputNode.querySelectorAll(".webconsole-msg-icon-container");
|
||||
is(msg.length, 3, "three message nodes displayed");
|
||||
is(msg[2].style.marginLeft, "0px", "correct group indent found");
|
||||
content.console.groupCollapsed("b");
|
||||
findLogEntry("b");
|
||||
let msg = outputNode.querySelectorAll(".webconsole-msg-icon-container");
|
||||
|
||||
content.console.groupCollapsed("bug664131b");
|
||||
|
||||
waitForSuccess({
|
||||
name: "console.groupCollapsed displayed",
|
||||
validatorFn: function()
|
||||
{
|
||||
return outputNode.textContent.indexOf("bug664131b") > -1;
|
||||
},
|
||||
successFn: testNext,
|
||||
failureFn: finishTest,
|
||||
});
|
||||
|
||||
yield;
|
||||
|
||||
msg = outputNode.querySelectorAll(".webconsole-msg-icon-container");
|
||||
is(msg.length, 4, "four message nodes displayed");
|
||||
is(msg[3].style.marginLeft, GROUP_INDENT + "px", "correct group indent found");
|
||||
|
||||
|
||||
// Test that clearing the console removes the indentation.
|
||||
hud.jsterm.clearOutput();
|
||||
content.console.log("cleared");
|
||||
findLogEntry("cleared");
|
||||
let msg = outputNode.querySelectorAll(".webconsole-msg-icon-container");
|
||||
content.console.log("bug664131-cleared");
|
||||
|
||||
waitForSuccess({
|
||||
name: "console.log displayed after clearOutput",
|
||||
validatorFn: function()
|
||||
{
|
||||
return outputNode.textContent.indexOf("bug664131-cleared") > -1;
|
||||
},
|
||||
successFn: testNext,
|
||||
failureFn: finishTest,
|
||||
});
|
||||
|
||||
yield;
|
||||
|
||||
msg = outputNode.querySelectorAll(".webconsole-msg-icon-container");
|
||||
is(msg.length, 1, "one message node displayed");
|
||||
is(msg[0].style.marginLeft, "0px", "correct group indent found");
|
||||
|
||||
testDriver = hud = null;
|
||||
finishTest();
|
||||
|
||||
yield;
|
||||
}
|
||||
|
||||
|
@ -42,15 +42,14 @@
|
||||
|
||||
function test() {
|
||||
addTab(getBrowserURL());
|
||||
browser.addEventListener("DOMContentLoaded", testChrome, false);
|
||||
browser.addEventListener("DOMContentLoaded", function onLoad() {
|
||||
browser.removeEventListener("DOMContentLoaded", onLoad, true);
|
||||
openConsole();
|
||||
testChrome(HUDService.getHudByWindow(content));
|
||||
}, true);
|
||||
}
|
||||
|
||||
function testChrome() {
|
||||
browser.removeEventListener("DOMContentLoaded", testChrome, false);
|
||||
|
||||
openConsole();
|
||||
|
||||
let hud = HUDService.getHudByWindow(content);
|
||||
function testChrome(hud) {
|
||||
ok(hud, "we have a console");
|
||||
|
||||
ok(hud.HUDBox, "we have the console display");
|
||||
@ -67,6 +66,7 @@ function testChrome() {
|
||||
jsterm.complete(jsterm.COMPLETE_HINT_ONLY);
|
||||
is(jsterm.completeNode.value, " ment", "'docu' completion");
|
||||
|
||||
finishTest();
|
||||
gBrowser.removeCurrentTab();
|
||||
executeSoon(finishTest);
|
||||
}
|
||||
|
||||
|
@ -41,25 +41,31 @@ const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/te
|
||||
|
||||
function test() {
|
||||
addTab(TEST_URI);
|
||||
browser.addEventListener("DOMContentLoaded", onLoad, false);
|
||||
browser.addEventListener("load", function onLoad() {
|
||||
browser.removeEventListener("load", onLoad, true);
|
||||
openConsole(null, consoleOpened);
|
||||
}, true);
|
||||
}
|
||||
|
||||
function onLoad() {
|
||||
browser.removeEventListener("DOMContentLoaded", onLoad, false);
|
||||
let doc = content.document;
|
||||
openConsole();
|
||||
let button = doc.querySelector("button");
|
||||
function consoleOpened(hud) {
|
||||
waitForSuccess({
|
||||
name: "two nodes displayed",
|
||||
validatorFn: function()
|
||||
{
|
||||
return hud.outputNode.querySelectorAll(".hud-msg-node").length == 2;
|
||||
},
|
||||
successFn: function()
|
||||
{
|
||||
let nodes = hud.outputNode.querySelectorAll(".hud-msg-node");
|
||||
ok(/start/.test(nodes[0].textContent), "start found");
|
||||
ok(/end/.test(nodes[1].textContent), "end found - complete!");
|
||||
|
||||
finishTest();
|
||||
},
|
||||
failureFn: finishTest,
|
||||
});
|
||||
|
||||
let button = content.document.querySelector("button");
|
||||
ok(button, "we have the button");
|
||||
EventUtils.sendMouseEvent({ type: "click" }, button, content);
|
||||
executeSoon(testButtonClicked);
|
||||
}
|
||||
|
||||
function testButtonClicked()
|
||||
{
|
||||
let outputNode = HUDService.getHudByWindow(content).outputNode;
|
||||
let nodes = outputNode.querySelectorAll(".hud-msg-node");
|
||||
is(nodes.length, 2, "two nodes");
|
||||
ok(/start/.test(nodes[0].textContent), "start found");
|
||||
ok(/end/.test(nodes[1].textContent), "end found - complete!");
|
||||
finishTest();
|
||||
}
|
||||
|
@ -42,27 +42,52 @@
|
||||
|
||||
const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/test-console.html";
|
||||
|
||||
let testDriver = null;
|
||||
let subtestDriver = null;
|
||||
|
||||
function test() {
|
||||
addTab(TEST_URI);
|
||||
|
||||
browser.addEventListener("DOMContentLoaded", onLoad, false);
|
||||
}
|
||||
|
||||
function onLoad() {
|
||||
browser.removeEventListener("DOMContentLoaded", onLoad, false);
|
||||
|
||||
openConsole();
|
||||
openConsole(null, function(aHud) {
|
||||
hud = aHud;
|
||||
hudId = hud.hudId;
|
||||
outputNode = hud.outputNode;
|
||||
testDriver = testGen();
|
||||
testDriver.next();
|
||||
});
|
||||
}
|
||||
|
||||
hud = HUDService.getHudByWindow(content);
|
||||
hudId = hud.hudId;
|
||||
outputNode = hud.outputNode;
|
||||
function testGen() {
|
||||
subtestGen("log");
|
||||
yield;
|
||||
|
||||
testConsoleLoggingAPI("log");
|
||||
testConsoleLoggingAPI("info");
|
||||
testConsoleLoggingAPI("warn");
|
||||
testConsoleLoggingAPI("error");
|
||||
testConsoleLoggingAPI("debug"); // bug 616742
|
||||
subtestGen("info");
|
||||
yield;
|
||||
|
||||
subtestGen("warn");
|
||||
yield;
|
||||
|
||||
subtestGen("error");
|
||||
yield;
|
||||
|
||||
subtestGen("debug"); // bug 616742
|
||||
yield;
|
||||
|
||||
testDriver = subtestDriver = null;
|
||||
finishTest();
|
||||
|
||||
yield;
|
||||
}
|
||||
|
||||
function subtestGen(aMethod) {
|
||||
subtestDriver = testConsoleLoggingAPI(aMethod);
|
||||
subtestDriver.next();
|
||||
}
|
||||
|
||||
function testConsoleLoggingAPI(aMethod) {
|
||||
@ -74,9 +99,21 @@ function testConsoleLoggingAPI(aMethod) {
|
||||
console[aMethod]("foo-bar-baz");
|
||||
console[aMethod]("bar-baz");
|
||||
|
||||
var nodes = outputNode.querySelectorAll(".hud-filtered-by-string");
|
||||
function nextTest() {
|
||||
subtestDriver.next();
|
||||
}
|
||||
|
||||
is(nodes.length, 1, "1 hidden " + aMethod + " node found (via classList)");
|
||||
waitForSuccess({
|
||||
name: "1 hidden " + aMethod + " node via string filtering",
|
||||
validatorFn: function()
|
||||
{
|
||||
return outputNode.querySelectorAll(".hud-filtered-by-string").length == 1;
|
||||
},
|
||||
successFn: nextTest,
|
||||
failureFn: nextTest,
|
||||
});
|
||||
|
||||
yield;
|
||||
|
||||
hud.jsterm.clearOutput();
|
||||
|
||||
@ -86,16 +123,34 @@ function testConsoleLoggingAPI(aMethod) {
|
||||
setStringFilter(hudId, "");
|
||||
HUDService.setFilterState(hudId, aMethod, false);
|
||||
console[aMethod]("foo-bar-baz");
|
||||
nodes = outputNode.querySelectorAll("description");
|
||||
|
||||
is(nodes.length, 1, aMethod + " logging turned off, 1 message hidden");
|
||||
waitForSuccess({
|
||||
name: "1 message hidden for " + aMethod + " (logging turned off)",
|
||||
validatorFn: function()
|
||||
{
|
||||
return outputNode.querySelectorAll("description").length == 1;
|
||||
},
|
||||
successFn: nextTest,
|
||||
failureFn: nextTest,
|
||||
});
|
||||
|
||||
yield;
|
||||
|
||||
hud.jsterm.clearOutput();
|
||||
HUDService.setFilterState(hudId, aMethod, true);
|
||||
console[aMethod]("foo-bar-baz");
|
||||
nodes = outputNode.querySelectorAll("description");
|
||||
|
||||
is(nodes.length, 1, aMethod + " logging turned on, 1 message shown");
|
||||
waitForSuccess({
|
||||
name: "1 message shown for " + aMethod + " (logging turned on)",
|
||||
validatorFn: function()
|
||||
{
|
||||
return outputNode.querySelectorAll("description").length == 1;
|
||||
},
|
||||
successFn: nextTest,
|
||||
failureFn: nextTest,
|
||||
});
|
||||
|
||||
yield;
|
||||
|
||||
hud.jsterm.clearOutput();
|
||||
setStringFilter(hudId, "");
|
||||
@ -103,9 +158,20 @@ function testConsoleLoggingAPI(aMethod) {
|
||||
// test for multiple arguments.
|
||||
console[aMethod]("foo", "bar");
|
||||
|
||||
let node = outputNode.querySelector(".hud-msg-node");
|
||||
ok(/foo bar/.test(node.textContent),
|
||||
"Emitted both console arguments");
|
||||
waitForSuccess({
|
||||
name: "show both console arguments for " + aMethod,
|
||||
validatorFn: function()
|
||||
{
|
||||
let node = outputNode.querySelector(".hud-msg-node");
|
||||
return node && /foo bar/.test(node.textContent);
|
||||
},
|
||||
successFn: nextTest,
|
||||
failureFn: nextTest,
|
||||
});
|
||||
|
||||
yield;
|
||||
testDriver.next();
|
||||
yield;
|
||||
}
|
||||
|
||||
function setStringFilter(aId, aValue) {
|
||||
|
@ -19,23 +19,30 @@ function test()
|
||||
}
|
||||
|
||||
function onLoad() {
|
||||
browser.removeEventListener("DOMContentLoaded", onLoad,
|
||||
false);
|
||||
executeSoon(testNewlines);
|
||||
browser.removeEventListener("DOMContentLoaded", onLoad, false);
|
||||
openConsole(null, testNewlines);
|
||||
}
|
||||
|
||||
function testNewlines() {
|
||||
openConsole();
|
||||
hud = HUDService.getHudByWindow(content);
|
||||
function testNewlines(aHud) {
|
||||
hud = aHud;
|
||||
hud.jsterm.clearOutput();
|
||||
|
||||
let console = content.wrappedJSObject.console;
|
||||
ok(console != null, "we have the console object");
|
||||
|
||||
for (let i = 0; i < 20; i++) {
|
||||
console.log("Hello world!");
|
||||
content.console.log("Hello world #" + i);
|
||||
}
|
||||
|
||||
waitForSuccess({
|
||||
name: "20 console.log messages displayed",
|
||||
validatorFn: function()
|
||||
{
|
||||
return hud.outputNode.itemCount == 20;
|
||||
},
|
||||
successFn: testClipboard,
|
||||
failureFn: finishTest,
|
||||
});
|
||||
}
|
||||
|
||||
function testClipboard() {
|
||||
let outputNode = hud.outputNode;
|
||||
|
||||
outputNode.selectAll();
|
||||
@ -44,7 +51,8 @@ function testNewlines() {
|
||||
let clipboardTexts = [];
|
||||
for (let i = 0; i < outputNode.itemCount; i++) {
|
||||
let item = outputNode.getItemAtIndex(i);
|
||||
clipboardTexts.push("[" + ConsoleUtils.timestampString(item.timestamp) +
|
||||
clipboardTexts.push("[" +
|
||||
WebConsoleUtils.l10n.timestampString(item.timestamp) +
|
||||
"] " + item.clipboardText);
|
||||
}
|
||||
|
||||
|
@ -44,16 +44,14 @@ const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/te
|
||||
|
||||
function test() {
|
||||
addTab(TEST_URI);
|
||||
browser.addEventListener("DOMContentLoaded", testExecutionScope, false);
|
||||
browser.addEventListener("load", function onLoad() {
|
||||
browser.removeEventListener("load", onLoad, true);
|
||||
openConsole(null, testExecutionScope);
|
||||
}, true);
|
||||
}
|
||||
|
||||
function testExecutionScope() {
|
||||
browser.removeEventListener("DOMContentLoaded", testExecutionScope,
|
||||
false);
|
||||
|
||||
openConsole();
|
||||
|
||||
let jsterm = HUDService.getHudByWindow(content).jsterm;
|
||||
function testExecutionScope(hud) {
|
||||
let jsterm = hud.jsterm;
|
||||
|
||||
jsterm.clearOutput();
|
||||
jsterm.execute("location;");
|
||||
@ -67,9 +65,6 @@ function testExecutionScope() {
|
||||
ok(nodes[0].textContent.indexOf(TEST_URI),
|
||||
"command was executed in the window scope");
|
||||
|
||||
jsterm.clearOutput();
|
||||
jsterm.history.splice(0, jsterm.history.length); // workaround for bug 592552
|
||||
|
||||
finishTest();
|
||||
executeSoon(finishTest);
|
||||
}
|
||||
|
||||
|
@ -48,15 +48,14 @@ const HISTORY_FORWARD = 1;
|
||||
|
||||
function test() {
|
||||
addTab(TEST_URI);
|
||||
browser.addEventListener("DOMContentLoaded", testHistory, false);
|
||||
browser.addEventListener("load", function onLoad() {
|
||||
browser.removeEventListener("load", onLoad, true);
|
||||
openConsole(null, testHistory);
|
||||
}, true);
|
||||
}
|
||||
|
||||
function testHistory() {
|
||||
browser.removeEventListener("DOMContentLoaded", testHistory, false);
|
||||
|
||||
openConsole();
|
||||
|
||||
let jsterm = HUDService.getHudByWindow(content).jsterm;
|
||||
function testHistory(hud) {
|
||||
let jsterm = hud.jsterm;
|
||||
let input = jsterm.inputNode;
|
||||
|
||||
let executeList = ["document", "window", "window.location"];
|
||||
@ -77,7 +76,6 @@ function testHistory() {
|
||||
jsterm.historyPeruse(HISTORY_BACK);
|
||||
is (input.value, executeList[0], "test that item is still still index 0");
|
||||
|
||||
|
||||
for (var i = 1; i < executeList.length; i++) {
|
||||
jsterm.historyPeruse(HISTORY_FORWARD);
|
||||
is (input.value, executeList[i], "check history next idx:" + i);
|
||||
@ -98,9 +96,6 @@ function testHistory() {
|
||||
jsterm.historyPeruse(HISTORY_BACK);
|
||||
is (input.value, executeList[idxLast], "check history next idx:" + idxLast);
|
||||
|
||||
jsterm.clearOutput();
|
||||
jsterm.history.splice(0, jsterm.history.length); // workaround for bug 592552
|
||||
|
||||
finishTest();
|
||||
executeSoon(finishTest);
|
||||
}
|
||||
|
||||
|
@ -45,7 +45,10 @@ let jsterm;
|
||||
|
||||
function test() {
|
||||
addTab(TEST_URI);
|
||||
browser.addEventListener("DOMContentLoaded", testJSTerm, false);
|
||||
browser.addEventListener("load", function onLoad() {
|
||||
browser.removeEventListener("load", onLoad, true);
|
||||
openConsole(null, testJSTerm);
|
||||
}, true);
|
||||
}
|
||||
|
||||
function checkResult(msg, desc, lines) {
|
||||
@ -55,13 +58,9 @@ function checkResult(msg, desc, lines) {
|
||||
desc);
|
||||
}
|
||||
|
||||
function testJSTerm()
|
||||
function testJSTerm(hud)
|
||||
{
|
||||
browser.removeEventListener("DOMContentLoaded", testJSTerm, false);
|
||||
|
||||
openConsole();
|
||||
|
||||
jsterm = HUDService.getHudByWindow(content).jsterm;
|
||||
jsterm = hud.jsterm;
|
||||
|
||||
jsterm.clearOutput();
|
||||
jsterm.execute("'id=' + $('header').getAttribute('id')");
|
||||
@ -155,5 +154,5 @@ function testJSTerm()
|
||||
checkResult("null", "null is null", 1);
|
||||
|
||||
jsterm = null;
|
||||
finishTest();
|
||||
executeSoon(finishTest);
|
||||
}
|
||||
|
@ -44,22 +44,35 @@ const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/te
|
||||
|
||||
function test() {
|
||||
addTab(TEST_URI);
|
||||
browser.addEventListener("DOMContentLoaded",
|
||||
testLiveFilteringOfMessageTypes, false);
|
||||
browser.addEventListener("load", function onLoad() {
|
||||
browser.removeEventListener("load", onLoad, true);
|
||||
openConsole(null, consoleOpened);
|
||||
}, true);
|
||||
}
|
||||
|
||||
function consoleOpened(aHud) {
|
||||
hud = aHud;
|
||||
hud.jsterm.clearOutput();
|
||||
|
||||
let console = content.console;
|
||||
|
||||
for (let i = 0; i < 50; i++) {
|
||||
console.log("http://www.example.com/" + i);
|
||||
}
|
||||
|
||||
waitForSuccess({
|
||||
name: "50 console.log messages displayed",
|
||||
validatorFn: function()
|
||||
{
|
||||
return hud.outputNode.itemCount == 50;
|
||||
},
|
||||
successFn: testLiveFilteringOfMessageTypes,
|
||||
failureFn: finishTest,
|
||||
});
|
||||
}
|
||||
|
||||
function testLiveFilteringOfMessageTypes() {
|
||||
browser.removeEventListener("DOMContentLoaded",
|
||||
testLiveFilteringOfMessageTypes, false);
|
||||
|
||||
openConsole();
|
||||
|
||||
hud = HUDService.getHudByWindow(content);
|
||||
let console = browser.contentWindow.wrappedJSObject.console;
|
||||
|
||||
for (let i = 0; i < 50; i++) {
|
||||
console.log("http://www.example.com/");
|
||||
}
|
||||
// TODO: bug 744732 - broken live filtering tests.
|
||||
|
||||
HUDService.setFilterState(hud.hudId, "log", false);
|
||||
is(countMessageNodes(), 0, "the log nodes are hidden when the " +
|
||||
|
@ -42,24 +42,38 @@
|
||||
|
||||
const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/test-console.html";
|
||||
|
||||
let hud;
|
||||
|
||||
function test() {
|
||||
addTab(TEST_URI);
|
||||
browser.addEventListener("DOMContentLoaded",
|
||||
testLiveFilteringOnSearchStrings, false);
|
||||
browser.addEventListener("load", function onLoad() {
|
||||
browser.removeEventListener("load", onLoad, true);
|
||||
openConsole(null, consoleOpened);
|
||||
}, true);
|
||||
}
|
||||
|
||||
function consoleOpened(aHud) {
|
||||
hud = aHud;
|
||||
hud.jsterm.clearOutput();
|
||||
let console = content.console;
|
||||
|
||||
for (let i = 0; i < 50; i++) {
|
||||
console.log("http://www.example.com/ " + i);
|
||||
}
|
||||
|
||||
waitForSuccess({
|
||||
name: "50 console.log messages displayed",
|
||||
validatorFn: function()
|
||||
{
|
||||
return hud.outputNode.itemCount == 50;
|
||||
},
|
||||
successFn: testLiveFilteringOnSearchStrings,
|
||||
failureFn: finishTest,
|
||||
});
|
||||
}
|
||||
|
||||
function testLiveFilteringOnSearchStrings() {
|
||||
browser.removeEventListener("DOMContentLoaded",
|
||||
testLiveFilteringOnSearchStrings, false);
|
||||
|
||||
openConsole();
|
||||
|
||||
hud = HUDService.getHudByWindow(content);
|
||||
let console = browser.contentWindow.wrappedJSObject.console;
|
||||
|
||||
for (let i = 0; i < 50; i++) {
|
||||
console.log("http://www.example.com/");
|
||||
}
|
||||
// TODO: bug 744732 - broken live filtering tests.
|
||||
|
||||
setStringFilter("http");
|
||||
isnot(countMessageNodes(), 0, "the log nodes are not hidden when the " +
|
||||
|
@ -45,17 +45,15 @@ const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/te
|
||||
|
||||
function test() {
|
||||
addTab(TEST_URI);
|
||||
browser.addEventListener("DOMContentLoaded", testLogNodeClasses, false);
|
||||
browser.addEventListener("load", function onLoad() {
|
||||
browser.removeEventListener("load", onLoad, true);
|
||||
openConsole(null, consoleOpened);
|
||||
}, true);
|
||||
}
|
||||
|
||||
function testLogNodeClasses() {
|
||||
browser.removeEventListener("DOMContentLoaded", testLogNodeClasses,
|
||||
false);
|
||||
|
||||
openConsole();
|
||||
|
||||
let console = browser.contentWindow.wrappedJSObject.console;
|
||||
let outputNode = HUDService.getHudByWindow(content).outputNode;
|
||||
function consoleOpened(aHud) {
|
||||
let console = content.console;
|
||||
outputNode = aHud.outputNode;
|
||||
|
||||
ok(console, "console exists");
|
||||
console.log("I am a log message");
|
||||
@ -63,8 +61,19 @@ function testLogNodeClasses() {
|
||||
console.info("I am an info message");
|
||||
console.warn("I am a warning message");
|
||||
|
||||
let domLogEntries =
|
||||
outputNode.childNodes;
|
||||
waitForSuccess({
|
||||
name: "console.warn displayed",
|
||||
validatorFn: function()
|
||||
{
|
||||
return aHud.outputNode.textContent.indexOf("a warning") > -1;
|
||||
},
|
||||
successFn: testLogNodeClasses,
|
||||
failureFn: finishTest,
|
||||
});
|
||||
}
|
||||
|
||||
function testLogNodeClasses() {
|
||||
let domLogEntries = outputNode.childNodes;
|
||||
|
||||
let count = outputNode.childNodes.length;
|
||||
ok(count > 0, "LogCount: " + count);
|
||||
|
@ -44,16 +44,18 @@ function test() {
|
||||
|
||||
function onLoad() {
|
||||
browser.removeEventListener("DOMContentLoaded", onLoad, false);
|
||||
openConsole();
|
||||
openConsole(null, function(hud) {
|
||||
content.console.log("a log message");
|
||||
|
||||
let console = content.wrappedJSObject.console;
|
||||
let outputNode = HUDService.getHudByWindow(content).outputNode;
|
||||
|
||||
console.log("a log message");
|
||||
|
||||
let node = outputNode.querySelectorAll(".hud-msg-node");
|
||||
|
||||
ok(node[0].getAttribute("id") && node[0].getAttribute != "", "we have a node id");
|
||||
closeConsole();
|
||||
finishTest();
|
||||
waitForSuccess({
|
||||
name: "console.log message shown with an ID attribute",
|
||||
validatorFn: function()
|
||||
{
|
||||
let node = hud.outputNode.querySelector(".hud-msg-node");
|
||||
return node && node.getAttribute("id");
|
||||
},
|
||||
successFn: finishTest,
|
||||
failureFn: finishTest,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@ -49,14 +49,13 @@ let testDriver;
|
||||
|
||||
function test() {
|
||||
addTab(TEST_URI);
|
||||
browser.addEventListener("DOMContentLoaded", testNetworkPanel, false);
|
||||
browser.addEventListener("load", function onLoad() {
|
||||
browser.removeEventListener("load", onLoad, true);
|
||||
openConsole(null, testNetworkPanel);
|
||||
}, true);
|
||||
}
|
||||
|
||||
function testNetworkPanel() {
|
||||
browser.removeEventListener("DOMContentLoaded", testNetworkPanel,
|
||||
false);
|
||||
openConsole();
|
||||
|
||||
testDriver = testGen();
|
||||
testDriver.next();
|
||||
}
|
||||
@ -100,6 +99,11 @@ function checkNodeKeyValue(aPanel, aId, aKey, aValue) {
|
||||
function testGen() {
|
||||
let filterBox = HUDService.getHudByWindow(content).filterBox;
|
||||
|
||||
let tempScope = {};
|
||||
Cu.import("resource:///modules/WebConsoleUtils.jsm", tempScope);
|
||||
let l10n = tempScope.WebConsoleUtils.l10n;
|
||||
tempScope = null;
|
||||
|
||||
var httpActivity = {
|
||||
url: "http://www.testpage.com",
|
||||
method: "GET",
|
||||
@ -438,7 +442,9 @@ function testGen() {
|
||||
responseImageCached: false
|
||||
});
|
||||
|
||||
let responseString = HUDService.getFormatStr("NetworkPanel.responseBodyUnableToDisplay.content", ["application/x-shockwave-flash"]);
|
||||
let responseString =
|
||||
l10n.getFormatStr("NetworkPanel.responseBodyUnableToDisplay.content",
|
||||
["application/x-shockwave-flash"]);
|
||||
checkNodeContent(networkPanel, "responseBodyUnknownTypeContent", responseString);
|
||||
networkPanel.panel.hidePopup();
|
||||
|
||||
@ -481,5 +487,6 @@ function testGen() {
|
||||
networkPanel.panel.hidePopup(); */
|
||||
|
||||
// All done!
|
||||
finish();
|
||||
testDriver = null;
|
||||
executeSoon(finishTest);
|
||||
}
|
||||
|
@ -45,17 +45,14 @@ const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/te
|
||||
|
||||
function test() {
|
||||
addTab(TEST_URI);
|
||||
browser.addEventListener("DOMContentLoaded", testNullAndUndefinedOutput,
|
||||
false);
|
||||
browser.addEventListener("load", function onLoad() {
|
||||
browser.removeEventListener("load", onLoad, true);
|
||||
openConsole(null, testNullAndUndefinedOutput);
|
||||
}, true);
|
||||
}
|
||||
|
||||
function testNullAndUndefinedOutput() {
|
||||
browser.removeEventListener("DOMContentLoaded",
|
||||
testNullAndUndefinedOutput, false);
|
||||
|
||||
openConsole();
|
||||
|
||||
let jsterm = HUDService.getHudByWindow(content).jsterm;
|
||||
function testNullAndUndefinedOutput(hud) {
|
||||
let jsterm = hud.jsterm;
|
||||
let outputNode = jsterm.outputNode;
|
||||
|
||||
jsterm.clearOutput();
|
||||
@ -72,9 +69,6 @@ function testNullAndUndefinedOutput() {
|
||||
is(nodes.length, 2, "2 nodes in output");
|
||||
ok(nodes[1].textContent.indexOf("undefined") > -1, "'undefined' printed to output");
|
||||
|
||||
jsterm.clearOutput();
|
||||
jsterm.history.splice(0, jsterm.history.length); // workaround for bug 592552
|
||||
|
||||
finishTest();
|
||||
executeSoon(finishTest);
|
||||
}
|
||||
|
||||
|
@ -45,34 +45,36 @@ const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/te
|
||||
|
||||
function test() {
|
||||
addTab(TEST_URI);
|
||||
browser.addEventListener("DOMContentLoaded", testOutputOrder, false);
|
||||
browser.addEventListener("load", function onLoad() {
|
||||
browser.removeEventListener("load", onLoad, true);
|
||||
openConsole(null, testOutputOrder);
|
||||
}, true);
|
||||
}
|
||||
|
||||
function testOutputOrder() {
|
||||
browser.removeEventListener("DOMContentLoaded", testOutputOrder, false);
|
||||
|
||||
openConsole();
|
||||
|
||||
let jsterm = HUDService.getHudByWindow(content).jsterm;
|
||||
function testOutputOrder(hud) {
|
||||
let jsterm = hud.jsterm;
|
||||
let outputNode = jsterm.outputNode;
|
||||
|
||||
jsterm.clearOutput();
|
||||
jsterm.execute("console.log('foo', 'bar');");
|
||||
|
||||
let nodes = outputNode.querySelectorAll(".hud-msg-node");
|
||||
is(nodes.length, 3, "3 children in output");
|
||||
|
||||
let executedStringFirst =
|
||||
/console\.log\('foo', 'bar'\);/.test(nodes[0].textContent);
|
||||
|
||||
let outputSecond =
|
||||
/foo bar/.test(nodes[1].textContent);
|
||||
|
||||
ok(executedStringFirst && outputSecond, "executed string comes first");
|
||||
|
||||
jsterm.clearOutput();
|
||||
jsterm.history.splice(0, jsterm.history.length); // workaround for bug 592552
|
||||
|
||||
finishTest();
|
||||
waitForSuccess({
|
||||
name: "console.log message displayed",
|
||||
validatorFn: function()
|
||||
{
|
||||
return outputNode.querySelectorAll(".hud-msg-node").length == 3;
|
||||
},
|
||||
successFn: function()
|
||||
{
|
||||
let nodes = outputNode.querySelectorAll(".hud-msg-node");
|
||||
let executedStringFirst =
|
||||
/console\.log\('foo', 'bar'\);/.test(nodes[0].textContent);
|
||||
let outputSecond = /foo bar/.test(nodes[2].textContent);
|
||||
ok(executedStringFirst && outputSecond, "executed string comes first");
|
||||
jsterm.clearOutput();
|
||||
jsterm.history.splice(0, jsterm.history.length); // workaround for bug 592552
|
||||
finishTest();
|
||||
},
|
||||
failureFn: finishTest,
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -88,7 +88,7 @@ function onLoad() {
|
||||
is(hudRef.positionMenuitems.below.getAttribute("checked"), "true",
|
||||
"position menu checkbox is below");
|
||||
|
||||
finishTest();
|
||||
executeSoon(finishTest);
|
||||
}, false);
|
||||
|
||||
let diffHeight = Math.abs(hudBox.clientHeight - boxHeight);
|
||||
|
@ -57,7 +57,7 @@ function testRegistries() {
|
||||
ok(hud, "we have a HUD");
|
||||
ok(HUDService.hudReferences[hud.hudId], "we have a HUD in hudReferences");
|
||||
|
||||
let windowID = HUDService.getWindowId(content);
|
||||
let windowID = WebConsoleUtils.getOuterWindowId(content);
|
||||
is(HUDService.windowIds[windowID], hud.hudId, "windowIds are working");
|
||||
|
||||
finishTest();
|
||||
|
@ -7,27 +7,37 @@
|
||||
const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/test-error.html";
|
||||
|
||||
function test() {
|
||||
expectUncaughtException();
|
||||
addTab(TEST_URI);
|
||||
browser.addEventListener("DOMContentLoaded", testViewSource, false);
|
||||
browser.addEventListener("load", function onLoad() {
|
||||
browser.removeEventListener("load", onLoad, true);
|
||||
openConsole(null, testViewSource);
|
||||
}, true);
|
||||
}
|
||||
|
||||
function testViewSource() {
|
||||
browser.removeEventListener("DOMContentLoaded", testViewSource, false);
|
||||
|
||||
openConsole();
|
||||
|
||||
function testViewSource(hud) {
|
||||
let button = content.document.querySelector("button");
|
||||
button = XPCNativeWrapper.unwrap(button);
|
||||
ok(button, "we have the button on the page");
|
||||
|
||||
button.addEventListener("click", buttonClicked, false);
|
||||
expectUncaughtException();
|
||||
EventUtils.sendMouseEvent({ type: "click" }, button, content);
|
||||
}
|
||||
|
||||
function buttonClicked(aEvent) {
|
||||
aEvent.target.removeEventListener("click", buttonClicked, false);
|
||||
executeSoon(findLocationNode);
|
||||
waitForSuccess({
|
||||
name: "find the location node",
|
||||
validatorFn: function()
|
||||
{
|
||||
return hud.outputNode.querySelector(".webconsole-location");
|
||||
},
|
||||
successFn: function()
|
||||
{
|
||||
let locationNode = hud.outputNode.querySelector(".webconsole-location");
|
||||
|
||||
Services.ww.registerNotification(observer);
|
||||
|
||||
EventUtils.sendMouseEvent({ type: "click" }, locationNode);
|
||||
},
|
||||
failureFn: finishTest,
|
||||
});
|
||||
}
|
||||
|
||||
let observer = {
|
||||
@ -39,8 +49,6 @@ let observer = {
|
||||
ok(true, "the view source window was opened in response to clicking " +
|
||||
"the location node");
|
||||
|
||||
Services.ww.unregisterNotification(this);
|
||||
|
||||
// executeSoon() is necessary to avoid crashing Firefox. See bug 611543.
|
||||
executeSoon(function() {
|
||||
aSubject.close();
|
||||
@ -49,14 +57,6 @@ let observer = {
|
||||
}
|
||||
};
|
||||
|
||||
function findLocationNode() {
|
||||
outputNode = HUDService.getHudByWindow(content).outputNode;
|
||||
|
||||
let locationNode = outputNode.querySelector(".webconsole-location");
|
||||
ok(locationNode, "we have the location node");
|
||||
|
||||
Services.ww.registerNotification(observer);
|
||||
|
||||
EventUtils.sendMouseEvent({ type: "click" }, locationNode);
|
||||
}
|
||||
|
||||
registerCleanupFunction(function() {
|
||||
Services.ww.unregisterNotification(observer);
|
||||
});
|
||||
|
@ -8,7 +8,10 @@ const POSITION_PREF = "devtools.webconsole.position";
|
||||
|
||||
function test() {
|
||||
addTab(TEST_URI);
|
||||
browser.addEventListener("DOMContentLoaded", onLoad, false);
|
||||
browser.addEventListener("load", function onLoad() {
|
||||
browser.removeEventListener("load", onLoad, true);
|
||||
openConsole(null, consoleOpened);
|
||||
}, true);
|
||||
registerCleanupFunction(testEnd);
|
||||
}
|
||||
|
||||
@ -16,13 +19,7 @@ function testEnd() {
|
||||
Services.prefs.clearUserPref(POSITION_PREF);
|
||||
}
|
||||
|
||||
function onLoad() {
|
||||
browser.removeEventListener("DOMContentLoaded", onLoad, false);
|
||||
|
||||
openConsole();
|
||||
|
||||
let hudId = HUDService.getHudIdByWindow(content);
|
||||
let hudRef = HUDService.hudReferences[hudId];
|
||||
function consoleOpened(hudRef) {
|
||||
let hudBox = hudRef.HUDBox;
|
||||
|
||||
// listen for the panel popupshown event.
|
||||
@ -33,7 +30,7 @@ function onLoad() {
|
||||
|
||||
document.addEventListener("popuphidden", function popupHidden() {
|
||||
document.removeEventListener("popuphidden", popupHidden, false);
|
||||
finishTest();
|
||||
executeSoon(finishTest);
|
||||
}, false);
|
||||
|
||||
// Close the window console via the menu item
|
||||
|
@ -40,6 +40,8 @@ let tempScope = {};
|
||||
Cu.import("resource:///modules/HUDService.jsm", tempScope);
|
||||
let HUDService = tempScope.HUDService;
|
||||
let ConsoleUtils = tempScope.ConsoleUtils;
|
||||
Cu.import("resource:///modules/WebConsoleUtils.jsm", tempScope);
|
||||
let WebConsoleUtils = tempScope.WebConsoleUtils;
|
||||
|
||||
function log(aMsg)
|
||||
{
|
||||
@ -153,29 +155,83 @@ function findLogEntry(aString)
|
||||
testLogEntry(outputNode, aString, "found " + aString);
|
||||
}
|
||||
|
||||
function openConsole()
|
||||
/**
|
||||
* Open the Web Console for the given tab.
|
||||
*
|
||||
* @param nsIDOMElement [aTab]
|
||||
* Optional tab element for which you want open the Web Console. The
|
||||
* default tab is taken from the global variable |tab|.
|
||||
* @param function [aCallback]
|
||||
* Optional function to invoke after the Web Console completes
|
||||
* initialization (web-console-created).
|
||||
*/
|
||||
function openConsole(aTab, aCallback)
|
||||
{
|
||||
HUDService.activateHUDForContext(tab);
|
||||
function onWebConsoleOpen(aSubject, aTopic)
|
||||
{
|
||||
if (aTopic == "web-console-created") {
|
||||
Services.obs.removeObserver(onWebConsoleOpen, "web-console-created");
|
||||
aSubject.QueryInterface(Ci.nsISupportsString);
|
||||
let hud = HUDService.getHudReferenceById(aSubject.data);
|
||||
executeSoon(aCallback.bind(null, hud));
|
||||
}
|
||||
}
|
||||
|
||||
if (aCallback) {
|
||||
Services.obs.addObserver(onWebConsoleOpen, "web-console-created", false);
|
||||
}
|
||||
|
||||
HUDService.activateHUDForContext(aTab || tab);
|
||||
}
|
||||
|
||||
function closeConsole()
|
||||
/**
|
||||
* Close the Web Console for the given tab.
|
||||
*
|
||||
* @param nsIDOMElement [aTab]
|
||||
* Optional tab element for which you want close the Web Console. The
|
||||
* default tab is taken from the global variable |tab|.
|
||||
* @param function [aCallback]
|
||||
* Optional function to invoke after the Web Console completes
|
||||
* closing (web-console-destroyed).
|
||||
*/
|
||||
function closeConsole(aTab, aCallback)
|
||||
{
|
||||
HUDService.deactivateHUDForContext(tab);
|
||||
function onWebConsoleClose(aSubject, aTopic)
|
||||
{
|
||||
if (aTopic == "web-console-destroyed") {
|
||||
Services.obs.removeObserver(onWebConsoleClose, "web-console-destroyed");
|
||||
aSubject.QueryInterface(Ci.nsISupportsString);
|
||||
let hudId = aSubject.data;
|
||||
executeSoon(aCallback.bind(null, hudId));
|
||||
}
|
||||
}
|
||||
|
||||
if (aCallback) {
|
||||
Services.obs.addObserver(onWebConsoleClose, "web-console-destroyed", false);
|
||||
}
|
||||
|
||||
HUDService.deactivateHUDForContext(aTab || tab);
|
||||
}
|
||||
|
||||
function finishTest()
|
||||
{
|
||||
finish();
|
||||
browser = hudId = hud = filterBox = outputNode = cs = null;
|
||||
|
||||
let hud = HUDService.getHudByWindow(content);
|
||||
if (!hud) {
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
hud.jsterm.clearOutput(true);
|
||||
|
||||
closeConsole(hud.tab, finish);
|
||||
|
||||
hud = null;
|
||||
}
|
||||
|
||||
function tearDown()
|
||||
{
|
||||
try {
|
||||
HUDService.deactivateHUDForContext(gBrowser.selectedTab);
|
||||
}
|
||||
catch (ex) {
|
||||
log(ex);
|
||||
}
|
||||
HUDService.deactivateHUDForContext(gBrowser.selectedTab);
|
||||
while (gBrowser.tabs.length > 1) {
|
||||
gBrowser.removeCurrentTab();
|
||||
}
|
||||
@ -186,3 +242,49 @@ registerCleanupFunction(tearDown);
|
||||
|
||||
waitForExplicitFinish();
|
||||
|
||||
/**
|
||||
* Polls a given function waiting for it to become true.
|
||||
*
|
||||
* @param object aOptions
|
||||
* Options object with the following properties:
|
||||
* - validatorFn
|
||||
* A validator function that returns a boolean. This is called every few
|
||||
* milliseconds to check if the result is true. When it is true, succesFn
|
||||
* is called and polling stops. If validatorFn never returns true, then
|
||||
* polling timeouts after several tries and a failure is recorded.
|
||||
* - successFn
|
||||
* A function called when the validator function returns true.
|
||||
* - failureFn
|
||||
* A function called if the validator function timeouts - fails to return
|
||||
* true in the given time.
|
||||
* - name
|
||||
* Name of test. This is used to generate the success and failure
|
||||
* messages.
|
||||
* - timeout
|
||||
* Timeout for validator function, in milliseconds. Default is 5000.
|
||||
*/
|
||||
function waitForSuccess(aOptions)
|
||||
{
|
||||
let start = Date.now();
|
||||
let timeout = aOptions.timeout || 5000;
|
||||
|
||||
function wait(validatorFn, successFn, failureFn)
|
||||
{
|
||||
if ((Date.now() - start) > timeout) {
|
||||
// Log the failure.
|
||||
ok(false, "Timed out while waiting for: " + aOptions.name);
|
||||
failureFn(aOptions);
|
||||
return;
|
||||
}
|
||||
|
||||
if (validatorFn(aOptions)) {
|
||||
ok(true, aOptions.name);
|
||||
successFn();
|
||||
}
|
||||
else {
|
||||
setTimeout(function() wait(validatorFn, successFn, failureFn), 100);
|
||||
}
|
||||
}
|
||||
|
||||
wait(aOptions.validatorFn, aOptions.successFn, aOptions.failureFn);
|
||||
}
|
||||
|
@ -899,8 +899,11 @@ nsFrameScriptExecutor::Traverse(nsFrameScriptExecutor *tmp,
|
||||
nsCycleCollectionTraversalCallback &cb)
|
||||
{
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mGlobal)
|
||||
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mCx");
|
||||
nsContentUtils::XPConnect()->NoteJSContext(tmp->mCx, cb);
|
||||
nsIXPConnect* xpc = nsContentUtils::XPConnect();
|
||||
if (xpc) {
|
||||
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mCx");
|
||||
xpc->NoteJSContext(tmp->mCx, cb);
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS1(nsScriptCacheCleaner, nsIObserver)
|
||||
|
Loading…
Reference in New Issue
Block a user