зеркало из https://github.com/mozilla/gecko-dev.git
Bug 793996 - Create reload marker in the Web Console; r=robcee
This commit is contained in:
Родитель
a1f817b16f
Коммит
f94af751ab
|
@ -0,0 +1,311 @@
|
||||||
|
/* vim: set ts=2 et sw=2 tw=80: */
|
||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
const Heritage = require("sdk/core/heritage");
|
||||||
|
const XHTML_NS = "http://www.w3.org/1999/xhtml";
|
||||||
|
const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
|
||||||
|
|
||||||
|
// Constants for compatibility with the Web Console output implementation before
|
||||||
|
// bug 778766.
|
||||||
|
// TODO: remove these once bug 778766 is fixed.
|
||||||
|
const COMPAT = {
|
||||||
|
// The various categories of messages.
|
||||||
|
CATEGORIES: {
|
||||||
|
NETWORK: 0,
|
||||||
|
CSS: 1,
|
||||||
|
JS: 2,
|
||||||
|
WEBDEV: 3,
|
||||||
|
INPUT: 4,
|
||||||
|
OUTPUT: 5,
|
||||||
|
SECURITY: 6,
|
||||||
|
},
|
||||||
|
|
||||||
|
// The possible message severities.
|
||||||
|
SEVERITIES: {
|
||||||
|
ERROR: 0,
|
||||||
|
WARNING: 1,
|
||||||
|
INFO: 2,
|
||||||
|
LOG: 3,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The ConsoleOutput object is used to manage output of messages in the Web
|
||||||
|
* Console.
|
||||||
|
*
|
||||||
|
* @constructor
|
||||||
|
* @param object owner
|
||||||
|
* The console output owner. This usually the WebConsoleFrame instance.
|
||||||
|
* Any other object can be used, as long as it has the following
|
||||||
|
* properties and methods:
|
||||||
|
* - window
|
||||||
|
* - document
|
||||||
|
* - outputMessage(category, methodOrNode[, methodArguments])
|
||||||
|
* TODO: this is needed temporarily, until bug 778766 is fixed.
|
||||||
|
*/
|
||||||
|
function ConsoleOutput(owner)
|
||||||
|
{
|
||||||
|
this.owner = owner;
|
||||||
|
this._onFlushOutputMessage = this._onFlushOutputMessage.bind(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
ConsoleOutput.prototype = {
|
||||||
|
/**
|
||||||
|
* The document that holds the output.
|
||||||
|
* @type DOMDocument
|
||||||
|
*/
|
||||||
|
get document() this.owner.document,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The DOM window that holds the output.
|
||||||
|
* @type Window
|
||||||
|
*/
|
||||||
|
get window() this.owner.window,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a message to output.
|
||||||
|
*
|
||||||
|
* @param object ...args
|
||||||
|
* Any number of Message objects.
|
||||||
|
* @return this
|
||||||
|
*/
|
||||||
|
addMessage: function(...args)
|
||||||
|
{
|
||||||
|
for (let msg of args) {
|
||||||
|
msg.init(this);
|
||||||
|
this.owner.outputMessage(msg._categoryCompat, this._onFlushOutputMessage,
|
||||||
|
[msg]);
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Message renderer used for compatibility with the current Web Console output
|
||||||
|
* implementation. This method is invoked for every message object that is
|
||||||
|
* flushed to output. The message object is initialized and rendered, then it
|
||||||
|
* is displayed.
|
||||||
|
*
|
||||||
|
* TODO: remove this method once bug 778766 is fixed.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @param object message
|
||||||
|
* The message object to render.
|
||||||
|
* @return DOMElement
|
||||||
|
* The message DOM element that can be added to the console output.
|
||||||
|
*/
|
||||||
|
_onFlushOutputMessage: function(message)
|
||||||
|
{
|
||||||
|
return message.render().element;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destroy this ConsoleOutput instance.
|
||||||
|
*/
|
||||||
|
destroy: function()
|
||||||
|
{
|
||||||
|
this.owner = null;
|
||||||
|
},
|
||||||
|
}; // ConsoleOutput.prototype
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Message objects container.
|
||||||
|
* @type object
|
||||||
|
*/
|
||||||
|
let Messages = {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The BaseMessage object is used for all types of messages. Every kind of
|
||||||
|
* message should use this object as its base.
|
||||||
|
*
|
||||||
|
* @constructor
|
||||||
|
*/
|
||||||
|
Messages.BaseMessage = function()
|
||||||
|
{
|
||||||
|
this.widgets = new Set();
|
||||||
|
};
|
||||||
|
|
||||||
|
Messages.BaseMessage.prototype = {
|
||||||
|
/**
|
||||||
|
* Reference to the ConsoleOutput owner.
|
||||||
|
*
|
||||||
|
* @type object|null
|
||||||
|
* This is |null| if the message is not yet initialized.
|
||||||
|
*/
|
||||||
|
output: null,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reference to the parent message object, if this message is in a group or if
|
||||||
|
* it is otherwise owned by another message.
|
||||||
|
*
|
||||||
|
* @type object|null
|
||||||
|
*/
|
||||||
|
parent: null,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Message DOM element.
|
||||||
|
*
|
||||||
|
* @type DOMElement|null
|
||||||
|
* This is |null| if the message is not yet rendered.
|
||||||
|
*/
|
||||||
|
element: null,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tells if this message is visible or not.
|
||||||
|
* @type boolean
|
||||||
|
*/
|
||||||
|
get visible() {
|
||||||
|
return this.element && this.element.parentNode;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Holds the text-only representation of the message.
|
||||||
|
* @type string
|
||||||
|
*/
|
||||||
|
textContent: "",
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set of widgets included in this message.
|
||||||
|
* @type Set
|
||||||
|
*/
|
||||||
|
widgets: null,
|
||||||
|
|
||||||
|
// Properties that allow compatibility with the current Web Console output
|
||||||
|
// implementation.
|
||||||
|
_elementClassCompat: "",
|
||||||
|
_categoryCompat: null,
|
||||||
|
_severityCompat: null,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize the message.
|
||||||
|
*
|
||||||
|
* @param object output
|
||||||
|
* The ConsoleOutput owner.
|
||||||
|
* @param object [parent=null]
|
||||||
|
* Optional: a different message object that owns this instance.
|
||||||
|
* @return this
|
||||||
|
*/
|
||||||
|
init: function(output, parent=null)
|
||||||
|
{
|
||||||
|
this.output = output;
|
||||||
|
this.parent = parent;
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Render the message. After this method is invoked the |element| property
|
||||||
|
* will point to the DOM element of this message.
|
||||||
|
* @return this
|
||||||
|
*/
|
||||||
|
render: function()
|
||||||
|
{
|
||||||
|
if (!this.element) {
|
||||||
|
this.element = this._renderCompat();
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prepare the message container for the Web Console, such that it is
|
||||||
|
* compatible with the current implementation.
|
||||||
|
* TODO: remove this once bug 778766.
|
||||||
|
*/
|
||||||
|
_renderCompat: function()
|
||||||
|
{
|
||||||
|
let doc = this.output.document;
|
||||||
|
let container = doc.createElementNS(XUL_NS, "richlistitem");
|
||||||
|
container.setAttribute("id", "console-msg-" + gSequenceId());
|
||||||
|
container.setAttribute("class", "hud-msg-node " + this._elementClassCompat);
|
||||||
|
container.category = this._categoryCompat;
|
||||||
|
container.severity = this._severityCompat;
|
||||||
|
container.clipboardText = this.textContent;
|
||||||
|
container.timestamp = this.timestamp;
|
||||||
|
container._messageObject = this;
|
||||||
|
|
||||||
|
let body = doc.createElementNS(XUL_NS, "description");
|
||||||
|
body.flex = 1;
|
||||||
|
body.classList.add("webconsole-msg-body");
|
||||||
|
container.appendChild(body);
|
||||||
|
|
||||||
|
return container;
|
||||||
|
},
|
||||||
|
}; // Messages.BaseMessage.prototype
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The NavigationMarker is used to show a page load event.
|
||||||
|
*
|
||||||
|
* @constructor
|
||||||
|
* @extends Messages.BaseMessage
|
||||||
|
* @param string url
|
||||||
|
* The URL to display.
|
||||||
|
* @param number timestamp
|
||||||
|
* The message date and time, milliseconds elapsed since 1 January 1970
|
||||||
|
* 00:00:00 UTC.
|
||||||
|
*/
|
||||||
|
Messages.NavigationMarker = function(url, timestamp)
|
||||||
|
{
|
||||||
|
Messages.BaseMessage.apply(this, arguments);
|
||||||
|
this._url = url;
|
||||||
|
this.textContent = "------ " + url;
|
||||||
|
this.timestamp = timestamp;
|
||||||
|
};
|
||||||
|
|
||||||
|
Messages.NavigationMarker.prototype = Heritage.extend(Messages.BaseMessage.prototype,
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Message timestamp.
|
||||||
|
*
|
||||||
|
* @type number
|
||||||
|
* Milliseconds elapsed since 1 January 1970 00:00:00 UTC.
|
||||||
|
*/
|
||||||
|
timestamp: 0,
|
||||||
|
|
||||||
|
// Class names in order: category, severity then the class for the filter.
|
||||||
|
_elementClassCompat: "webconsole-msg-network webconsole-msg-info hud-networkinfo",
|
||||||
|
_categoryCompat: COMPAT.CATEGORIES.NETWORK,
|
||||||
|
_severityCompat: COMPAT.SEVERITIES.LOG,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prepare the DOM element for this message.
|
||||||
|
* @return this
|
||||||
|
*/
|
||||||
|
render: function()
|
||||||
|
{
|
||||||
|
if (this.element) {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
let url = this._url;
|
||||||
|
let pos = url.indexOf("?");
|
||||||
|
if (pos > -1) {
|
||||||
|
url = url.substr(0, pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
let doc = this.output.document;
|
||||||
|
let urlnode = doc.createElementNS(XHTML_NS, "span");
|
||||||
|
urlnode.className = "url";
|
||||||
|
urlnode.textContent = url;
|
||||||
|
|
||||||
|
// Add the text in the xul:description.webconsole-msg-body element.
|
||||||
|
let render = Messages.BaseMessage.prototype.render.bind(this);
|
||||||
|
render().element.firstChild.appendChild(urlnode);
|
||||||
|
this.element.classList.add("navigation-marker");
|
||||||
|
this.element.url = this._url;
|
||||||
|
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
}); // Messages.NavigationMarker.prototype
|
||||||
|
|
||||||
|
|
||||||
|
function gSequenceId()
|
||||||
|
{
|
||||||
|
return gSequenceId.n++;
|
||||||
|
}
|
||||||
|
gSequenceId.n = 0;
|
||||||
|
|
||||||
|
exports.ConsoleOutput = ConsoleOutput;
|
||||||
|
exports.Messages = Messages;
|
|
@ -17,7 +17,6 @@ MOCHITEST_BROWSER_FILES = \
|
||||||
browser_webconsole_basic_net_logging.js \
|
browser_webconsole_basic_net_logging.js \
|
||||||
browser_webconsole_bug_579412_input_focus.js \
|
browser_webconsole_bug_579412_input_focus.js \
|
||||||
browser_webconsole_bug_580001_closing_after_completion.js \
|
browser_webconsole_bug_580001_closing_after_completion.js \
|
||||||
browser_webconsole_bug_580400_groups.js \
|
|
||||||
browser_webconsole_bug_588730_text_node_insertion.js \
|
browser_webconsole_bug_588730_text_node_insertion.js \
|
||||||
browser_webconsole_bug_601667_filter_buttons.js \
|
browser_webconsole_bug_601667_filter_buttons.js \
|
||||||
browser_webconsole_bug_597136_external_script_errors.js \
|
browser_webconsole_bug_597136_external_script_errors.js \
|
||||||
|
@ -145,6 +144,7 @@ MOCHITEST_BROWSER_FILES = \
|
||||||
browser_console_variables_view_while_debugging_and_inspecting.js \
|
browser_console_variables_view_while_debugging_and_inspecting.js \
|
||||||
browser_webconsole_bug_686937_autocomplete_JSTerm_helpers.js \
|
browser_webconsole_bug_686937_autocomplete_JSTerm_helpers.js \
|
||||||
browser_webconsole_cached_autocomplete.js \
|
browser_webconsole_cached_autocomplete.js \
|
||||||
|
browser_console_navigation_marker.js \
|
||||||
head.js \
|
head.js \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,81 @@
|
||||||
|
/*
|
||||||
|
* Any copyright is dedicated to the Public Domain.
|
||||||
|
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Check that the navigation marker shows on page reload - bug 793996.
|
||||||
|
|
||||||
|
function test()
|
||||||
|
{
|
||||||
|
const PREF = "devtools.webconsole.persistlog";
|
||||||
|
const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/test-console.html";
|
||||||
|
let hud = null;
|
||||||
|
let Messages = require("devtools/webconsole/console-output").Messages;
|
||||||
|
|
||||||
|
Services.prefs.setBoolPref(PREF, true);
|
||||||
|
registerCleanupFunction(() => Services.prefs.clearUserPref(PREF));
|
||||||
|
|
||||||
|
addTab(TEST_URI);
|
||||||
|
|
||||||
|
browser.addEventListener("load", function onLoad() {
|
||||||
|
browser.removeEventListener("load", onLoad, true);
|
||||||
|
openConsole(null, consoleOpened);
|
||||||
|
}, true);
|
||||||
|
|
||||||
|
function consoleOpened(aHud)
|
||||||
|
{
|
||||||
|
hud = aHud;
|
||||||
|
ok(hud, "Web Console opened");
|
||||||
|
|
||||||
|
hud.jsterm.clearOutput();
|
||||||
|
content.console.log("foobarz1");
|
||||||
|
waitForMessages({
|
||||||
|
webconsole: hud,
|
||||||
|
messages: [{
|
||||||
|
text: "foobarz1",
|
||||||
|
category: CATEGORY_WEBDEV,
|
||||||
|
severity: SEVERITY_LOG,
|
||||||
|
}],
|
||||||
|
}).then(onConsoleMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
function onConsoleMessage()
|
||||||
|
{
|
||||||
|
browser.addEventListener("load", onReload, true);
|
||||||
|
content.location.reload();
|
||||||
|
}
|
||||||
|
|
||||||
|
function onReload()
|
||||||
|
{
|
||||||
|
browser.removeEventListener("load", onReload, true);
|
||||||
|
|
||||||
|
content.console.log("foobarz2");
|
||||||
|
|
||||||
|
waitForMessages({
|
||||||
|
webconsole: hud,
|
||||||
|
messages: [{
|
||||||
|
name: "page reload",
|
||||||
|
text: "test-console.html",
|
||||||
|
category: CATEGORY_NETWORK,
|
||||||
|
severity: SEVERITY_LOG,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: "foobarz2",
|
||||||
|
category: CATEGORY_WEBDEV,
|
||||||
|
severity: SEVERITY_LOG,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "navigation marker",
|
||||||
|
text: "test-console.html",
|
||||||
|
type: Messages.NavigationMarker,
|
||||||
|
}],
|
||||||
|
}).then(onConsoleMessageAfterReload);
|
||||||
|
}
|
||||||
|
|
||||||
|
function onConsoleMessageAfterReload()
|
||||||
|
{
|
||||||
|
isnot(hud.outputNode.textContent.indexOf("foobarz1"), -1,
|
||||||
|
"foobarz1 is still in the output");
|
||||||
|
finishTest();
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,78 +0,0 @@
|
||||||
/* vim:set ts=2 sw=2 sts=2 et: */
|
|
||||||
/* 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/. */
|
|
||||||
|
|
||||||
// Tests that console groups behave properly.
|
|
||||||
|
|
||||||
const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/test-console.html";
|
|
||||||
|
|
||||||
function test() {
|
|
||||||
addTab(TEST_URI);
|
|
||||||
browser.addEventListener("load", function onLoad() {
|
|
||||||
browser.removeEventListener("load", onLoad, true);
|
|
||||||
openConsole(null, testGroups);
|
|
||||||
}, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
function testGroups(HUD) {
|
|
||||||
let jsterm = HUD.jsterm;
|
|
||||||
let outputNode = HUD.outputNode;
|
|
||||||
jsterm.clearOutput();
|
|
||||||
|
|
||||||
// We test for one group by testing for zero "new" groups. The
|
|
||||||
// "webconsole-new-group" class creates a divider. Thus one group is
|
|
||||||
// indicated by zero new groups, two groups are indicated by one new group,
|
|
||||||
// and so on.
|
|
||||||
|
|
||||||
let waitForSecondMessage = {
|
|
||||||
name: "second console message",
|
|
||||||
validatorFn: function()
|
|
||||||
{
|
|
||||||
return outputNode.querySelectorAll(".webconsole-msg-output").length == 2;
|
|
||||||
},
|
|
||||||
successFn: function()
|
|
||||||
{
|
|
||||||
let timestamp1 = Date.now();
|
|
||||||
if (timestamp1 - timestamp0 < 5000) {
|
|
||||||
is(outputNode.querySelectorAll(".webconsole-new-group").length, 0,
|
|
||||||
"no group dividers exist after the second console message");
|
|
||||||
}
|
|
||||||
|
|
||||||
for (let i = 0; i < outputNode.itemCount; i++) {
|
|
||||||
outputNode.getItemAtIndex(i).timestamp = 0; // a "far past" value
|
|
||||||
}
|
|
||||||
|
|
||||||
jsterm.execute("2");
|
|
||||||
waitForSuccess(waitForThirdMessage);
|
|
||||||
},
|
|
||||||
failureFn: finishTest,
|
|
||||||
};
|
|
||||||
|
|
||||||
let waitForThirdMessage = {
|
|
||||||
name: "one group divider exists after the third console message",
|
|
||||||
validatorFn: function()
|
|
||||||
{
|
|
||||||
return outputNode.querySelectorAll(".webconsole-new-group").length == 1;
|
|
||||||
},
|
|
||||||
successFn: finishTest,
|
|
||||||
failureFn: finishTest,
|
|
||||||
};
|
|
||||||
|
|
||||||
let timestamp0 = Date.now();
|
|
||||||
jsterm.execute("0");
|
|
||||||
|
|
||||||
waitForSuccess({
|
|
||||||
name: "no group dividers exist after the first console message",
|
|
||||||
validatorFn: function()
|
|
||||||
{
|
|
||||||
return outputNode.querySelectorAll(".webconsole-new-group").length == 0;
|
|
||||||
},
|
|
||||||
successFn: function()
|
|
||||||
{
|
|
||||||
jsterm.execute("1");
|
|
||||||
waitForSuccess(waitForSecondMessage);
|
|
||||||
},
|
|
||||||
failureFn: finishTest,
|
|
||||||
});
|
|
||||||
}
|
|
|
@ -124,12 +124,20 @@ function testFormSubmission()
|
||||||
// There should be 3 network requests pointing to the HTML file.
|
// There should be 3 network requests pointing to the HTML file.
|
||||||
waitForMessages({
|
waitForMessages({
|
||||||
webconsole: hud,
|
webconsole: hud,
|
||||||
messages: [{
|
messages: [
|
||||||
text: "test-network-request.html",
|
{
|
||||||
category: CATEGORY_NETWORK,
|
text: "test-network-request.html",
|
||||||
severity: SEVERITY_LOG,
|
category: CATEGORY_NETWORK,
|
||||||
count: 3,
|
severity: SEVERITY_LOG,
|
||||||
}],
|
count: 3,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: "test-data.json",
|
||||||
|
category: CATEGORY_NETWORK,
|
||||||
|
severity: SEVERITY_LOG,
|
||||||
|
count: 2,
|
||||||
|
},
|
||||||
|
],
|
||||||
}).then(testLiveFilteringOnSearchStrings);
|
}).then(testLiveFilteringOnSearchStrings);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* 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/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
let WebConsoleUtils, gDevTools, TargetFactory, console, promise;
|
let WebConsoleUtils, gDevTools, TargetFactory, console, promise, require;
|
||||||
|
|
||||||
(() => {
|
(() => {
|
||||||
gDevTools = Cu.import("resource:///modules/devtools/gDevTools.jsm", {}).gDevTools;
|
gDevTools = Cu.import("resource:///modules/devtools/gDevTools.jsm", {}).gDevTools;
|
||||||
|
@ -14,6 +14,7 @@ let WebConsoleUtils, gDevTools, TargetFactory, console, promise;
|
||||||
let utils = tools.require("devtools/toolkit/webconsole/utils");
|
let utils = tools.require("devtools/toolkit/webconsole/utils");
|
||||||
TargetFactory = tools.TargetFactory;
|
TargetFactory = tools.TargetFactory;
|
||||||
WebConsoleUtils = utils.Utils;
|
WebConsoleUtils = utils.Utils;
|
||||||
|
require = tools.require;
|
||||||
})();
|
})();
|
||||||
// promise._reportErrors = true; // please never leave me.
|
// promise._reportErrors = true; // please never leave me.
|
||||||
|
|
||||||
|
@ -884,6 +885,9 @@ function getMessageElementText(aElement)
|
||||||
* message.
|
* message.
|
||||||
* - longString: boolean, set to |true} to match long strings in the
|
* - longString: boolean, set to |true} to match long strings in the
|
||||||
* message.
|
* message.
|
||||||
|
* - type: match messages that are instances of the given object. For
|
||||||
|
* example, you can point to Messages.NavigationMarker to match any
|
||||||
|
* such message.
|
||||||
* - objects: boolean, set to |true| if you expect inspectable
|
* - objects: boolean, set to |true| if you expect inspectable
|
||||||
* objects in the message.
|
* objects in the message.
|
||||||
* - source: object that can hold one property: url. This is used to
|
* - source: object that can hold one property: url. This is used to
|
||||||
|
@ -1063,8 +1067,25 @@ function waitForMessages(aOptions)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (aRule.type) {
|
||||||
|
// The rule tries to match the newer types of messages, based on their
|
||||||
|
// object constructor.
|
||||||
|
if (!aElement._messageObject ||
|
||||||
|
!(aElement._messageObject instanceof aRule.type)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (aElement._messageObject) {
|
||||||
|
// If the message element holds a reference to its object, it means this
|
||||||
|
// is a newer message type. All of the older waitForMessages() rules do
|
||||||
|
// not expect this kind of messages. We return false here.
|
||||||
|
// TODO: we keep this behavior until bug 778766 is fixed. After that we
|
||||||
|
// will not require |type| to match newer types of messages.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
let partialMatch = !!(aRule.consoleTrace || aRule.consoleTime ||
|
let partialMatch = !!(aRule.consoleTrace || aRule.consoleTime ||
|
||||||
aRule.consoleTimeEnd);
|
aRule.consoleTimeEnd || aRule.type);
|
||||||
|
|
||||||
if (aRule.category && aElement.category != aRule.category) {
|
if (aRule.category && aElement.category != aRule.category) {
|
||||||
if (partialMatch) {
|
if (partialMatch) {
|
||||||
|
|
|
@ -22,6 +22,10 @@ loader.lazyGetter(this, "ToolSidebar",
|
||||||
() => require("devtools/framework/sidebar").ToolSidebar);
|
() => require("devtools/framework/sidebar").ToolSidebar);
|
||||||
loader.lazyGetter(this, "NetworkPanel",
|
loader.lazyGetter(this, "NetworkPanel",
|
||||||
() => require("devtools/webconsole/network-panel").NetworkPanel);
|
() => require("devtools/webconsole/network-panel").NetworkPanel);
|
||||||
|
loader.lazyGetter(this, "ConsoleOutput",
|
||||||
|
() => require("devtools/webconsole/console-output").ConsoleOutput);
|
||||||
|
loader.lazyGetter(this, "Messages",
|
||||||
|
() => require("devtools/webconsole/console-output").Messages);
|
||||||
loader.lazyImporter(this, "GripClient", "resource://gre/modules/devtools/dbg-client.jsm");
|
loader.lazyImporter(this, "GripClient", "resource://gre/modules/devtools/dbg-client.jsm");
|
||||||
loader.lazyImporter(this, "VariablesView", "resource:///modules/devtools/VariablesView.jsm");
|
loader.lazyImporter(this, "VariablesView", "resource:///modules/devtools/VariablesView.jsm");
|
||||||
loader.lazyImporter(this, "VariablesViewController", "resource:///modules/devtools/VariablesViewController.jsm");
|
loader.lazyImporter(this, "VariablesViewController", "resource:///modules/devtools/VariablesViewController.jsm");
|
||||||
|
@ -187,6 +191,8 @@ function WebConsoleFrame(aWebConsoleOwner)
|
||||||
this._networkRequests = {};
|
this._networkRequests = {};
|
||||||
this.filterPrefs = {};
|
this.filterPrefs = {};
|
||||||
|
|
||||||
|
this.output = new ConsoleOutput(this);
|
||||||
|
|
||||||
this._toggleFilter = this._toggleFilter.bind(this);
|
this._toggleFilter = this._toggleFilter.bind(this);
|
||||||
this._flushMessageQueue = this._flushMessageQueue.bind(this);
|
this._flushMessageQueue = this._flushMessageQueue.bind(this);
|
||||||
|
|
||||||
|
@ -324,6 +330,12 @@ WebConsoleFrame.prototype = {
|
||||||
*/
|
*/
|
||||||
outputNode: null,
|
outputNode: null,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The ConsoleOutput instance that manages all output.
|
||||||
|
* @type object
|
||||||
|
*/
|
||||||
|
output: null,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The input element that allows the user to filter messages by string.
|
* The input element that allows the user to filter messages by string.
|
||||||
* @type nsIDOMElement
|
* @type nsIDOMElement
|
||||||
|
@ -830,8 +842,6 @@ WebConsoleFrame.prototype = {
|
||||||
node.classList.add("hud-filtered-by-type");
|
node.classList.add("hud-filtered-by-type");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.regroupOutput();
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -858,8 +868,6 @@ WebConsoleFrame.prototype = {
|
||||||
node.classList.add("hud-filtered-by-string");
|
node.classList.add("hud-filtered-by-string");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.regroupOutput();
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1750,6 +1758,35 @@ WebConsoleFrame.prototype = {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handler for the tabNavigated notification.
|
||||||
|
*
|
||||||
|
* @param string aEvent
|
||||||
|
* Event name.
|
||||||
|
* @param object aPacket
|
||||||
|
* Notification packet received from the server.
|
||||||
|
*/
|
||||||
|
handleTabNavigated: function WCF_handleTabNavigated(aEvent, aPacket)
|
||||||
|
{
|
||||||
|
if (aEvent == "will-navigate") {
|
||||||
|
if (this.persistLog) {
|
||||||
|
let marker = new Messages.NavigationMarker(aPacket.url, Date.now());
|
||||||
|
this.output.addMessage(marker);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.jsterm.clearOutput();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (aPacket.url) {
|
||||||
|
this.onLocationChange(aPacket.url, aPacket.title);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (aEvent == "navigate" && !aPacket.nativeConsoleAPI) {
|
||||||
|
this.logWarningAboutReplacedAPI();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Output a message node. This filters a node appropriately, then sends it to
|
* Output a message node. This filters a node appropriately, then sends it to
|
||||||
* the output, regrouping and pruning output as necessary.
|
* the output, regrouping and pruning output as necessary.
|
||||||
|
@ -1863,11 +1900,6 @@ WebConsoleFrame.prototype = {
|
||||||
this._pruneCategoriesQueue = {};
|
this._pruneCategoriesQueue = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Regroup messages at the end of the queue.
|
|
||||||
if (!this._outputQueue.length) {
|
|
||||||
this.regroupOutput();
|
|
||||||
}
|
|
||||||
|
|
||||||
let isInputOutput = lastVisibleNode &&
|
let isInputOutput = lastVisibleNode &&
|
||||||
(lastVisibleNode.classList.contains("webconsole-msg-input") ||
|
(lastVisibleNode.classList.contains("webconsole-msg-input") ||
|
||||||
lastVisibleNode.classList.contains("webconsole-msg-output"));
|
lastVisibleNode.classList.contains("webconsole-msg-output"));
|
||||||
|
@ -2136,29 +2168,6 @@ WebConsoleFrame.prototype = {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
|
||||||
* Splits the given console messages into groups based on their timestamps.
|
|
||||||
*/
|
|
||||||
regroupOutput: function WCF_regroupOutput()
|
|
||||||
{
|
|
||||||
// Go through the nodes and adjust the placement of "webconsole-new-group"
|
|
||||||
// classes.
|
|
||||||
let nodes = this.outputNode.querySelectorAll(".hud-msg-node" +
|
|
||||||
":not(.hud-filtered-by-string):not(.hud-filtered-by-type)");
|
|
||||||
let lastTimestamp;
|
|
||||||
for (let i = 0, n = nodes.length; i < n; i++) {
|
|
||||||
let thisTimestamp = nodes[i].timestamp;
|
|
||||||
if (lastTimestamp != null &&
|
|
||||||
thisTimestamp >= lastTimestamp + NEW_GROUP_DELAY) {
|
|
||||||
nodes[i].classList.add("webconsole-new-group");
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
nodes[i].classList.remove("webconsole-new-group");
|
|
||||||
}
|
|
||||||
lastTimestamp = thisTimestamp;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Given a category and message body, creates a DOM node to represent an
|
* Given a category and message body, creates a DOM node to represent an
|
||||||
* incoming message. The timestamp is automatically added.
|
* incoming message. The timestamp is automatically added.
|
||||||
|
@ -2622,7 +2631,6 @@ WebConsoleFrame.prototype = {
|
||||||
|
|
||||||
// Gather up the selected items and concatenate their clipboard text.
|
// Gather up the selected items and concatenate their clipboard text.
|
||||||
let strings = [];
|
let strings = [];
|
||||||
let newGroup = false;
|
|
||||||
|
|
||||||
let children = this.outputNode.children;
|
let children = this.outputNode.children;
|
||||||
|
|
||||||
|
@ -2632,21 +2640,10 @@ WebConsoleFrame.prototype = {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add dashes between groups so that group boundaries show up in the
|
|
||||||
// copied output.
|
|
||||||
if (i > 0 && item.classList.contains("webconsole-new-group")) {
|
|
||||||
newGroup = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ensure the selected item hasn't been filtered by type or string.
|
// Ensure the selected item hasn't been filtered by type or string.
|
||||||
if (!item.classList.contains("hud-filtered-by-type") &&
|
if (!item.classList.contains("hud-filtered-by-type") &&
|
||||||
!item.classList.contains("hud-filtered-by-string")) {
|
!item.classList.contains("hud-filtered-by-string")) {
|
||||||
let timestampString = l10n.timestampString(item.timestamp);
|
let timestampString = l10n.timestampString(item.timestamp);
|
||||||
if (newGroup) {
|
|
||||||
strings.push("--");
|
|
||||||
newGroup = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (aOptions.linkOnly) {
|
if (aOptions.linkOnly) {
|
||||||
strings.push(item.url);
|
strings.push(item.url);
|
||||||
}
|
}
|
||||||
|
@ -2741,6 +2738,9 @@ WebConsoleFrame.prototype = {
|
||||||
this.jsterm.destroy();
|
this.jsterm.destroy();
|
||||||
this.jsterm = null;
|
this.jsterm = null;
|
||||||
}
|
}
|
||||||
|
this.output.destroy();
|
||||||
|
this.output = null;
|
||||||
|
|
||||||
if (this._contextMenuHandler) {
|
if (this._contextMenuHandler) {
|
||||||
this._contextMenuHandler.destroy();
|
this._contextMenuHandler.destroy();
|
||||||
this._contextMenuHandler = null;
|
this._contextMenuHandler = null;
|
||||||
|
@ -4981,17 +4981,7 @@ WebConsoleConnectionProxy.prototype = {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (aEvent == "will-navigate" && !this.owner.persistLog) {
|
this.owner.handleTabNavigated(aEvent, aPacket);
|
||||||
this.owner.jsterm.clearOutput();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (aPacket.url) {
|
|
||||||
this.owner.onLocationChange(aPacket.url, aPacket.title);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (aEvent == "navigate" && !aPacket.nativeConsoleAPI) {
|
|
||||||
this.owner.logWarningAboutReplacedAPI();
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -272,3 +272,17 @@
|
||||||
.webconsole-msg-security.webconsole-msg-warn {
|
.webconsole-msg-security.webconsole-msg-warn {
|
||||||
-moz-image-region: rect(32px, 24px, 40px, 16px);
|
-moz-image-region: rect(32px, 24px, 40px, 16px);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.navigation-marker {
|
||||||
|
color: #aaa;
|
||||||
|
background: linear-gradient(#fff, #bbb, #fff) no-repeat left 50%;
|
||||||
|
background-size: 100% 2px;
|
||||||
|
-moz-margin-start: 3px;
|
||||||
|
-moz-margin-end: 6px;
|
||||||
|
font-size: 0.9em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.navigation-marker .url {
|
||||||
|
background: #fff;
|
||||||
|
-moz-padding-end: 6px;
|
||||||
|
}
|
||||||
|
|
Загрузка…
Ссылка в новой задаче