зеркало из https://github.com/mozilla/gecko-dev.git
Merge m-c to fx-team
This commit is contained in:
Коммит
096e1d6297
|
@ -1010,7 +1010,7 @@ pref("devtools.inspector.htmlHeight", 112);
|
|||
pref("devtools.inspector.htmlPanelOpen", false);
|
||||
pref("devtools.inspector.sidebarOpen", false);
|
||||
pref("devtools.inspector.activeSidebar", "ruleview");
|
||||
pref("devtools.inspector.markupPreview", true);
|
||||
pref("devtools.inspector.markupPreview", false);
|
||||
|
||||
// Enable the Layout View
|
||||
pref("devtools.layoutview.enabled", true);
|
||||
|
|
|
@ -28,79 +28,82 @@ gcli.addCommand({
|
|||
description: gcli.lookup('jsbUrlDesc')
|
||||
},
|
||||
{
|
||||
name: 'indentSize',
|
||||
type: 'number',
|
||||
description: gcli.lookup('jsbIndentSizeDesc'),
|
||||
manual: gcli.lookup('jsbIndentSizeManual'),
|
||||
defaultValue: 2
|
||||
},
|
||||
{
|
||||
name: 'indentChar',
|
||||
type: {
|
||||
name: 'selection',
|
||||
lookup: [
|
||||
{ name: "space", value: " " },
|
||||
{ name: "tab", value: "\t" }
|
||||
]
|
||||
},
|
||||
description: gcli.lookup('jsbIndentCharDesc'),
|
||||
manual: gcli.lookup('jsbIndentCharManual'),
|
||||
defaultValue: ' ',
|
||||
},
|
||||
{
|
||||
name: 'preserveNewlines',
|
||||
type: 'boolean',
|
||||
description: gcli.lookup('jsbPreserveNewlinesDesc'),
|
||||
manual: gcli.lookup('jsbPreserveNewlinesManual')
|
||||
},
|
||||
{
|
||||
name: 'preserveMaxNewlines',
|
||||
type: 'number',
|
||||
description: gcli.lookup('jsbPreserveMaxNewlinesDesc'),
|
||||
manual: gcli.lookup('jsbPreserveMaxNewlinesManual'),
|
||||
defaultValue: -1
|
||||
},
|
||||
{
|
||||
name: 'jslintHappy',
|
||||
type: 'boolean',
|
||||
description: gcli.lookup('jsbJslintHappyDesc'),
|
||||
manual: gcli.lookup('jsbJslintHappyManual')
|
||||
},
|
||||
{
|
||||
name: 'braceStyle',
|
||||
type: {
|
||||
name: 'selection',
|
||||
data: ['collapse', 'expand', 'end-expand', 'expand-strict']
|
||||
},
|
||||
description: gcli.lookup('jsbBraceStyleDesc'),
|
||||
manual: gcli.lookup('jsbBraceStyleManual'),
|
||||
defaultValue: "collapse"
|
||||
},
|
||||
{
|
||||
name: 'spaceBeforeConditional',
|
||||
type: 'boolean',
|
||||
description: gcli.lookup('jsbSpaceBeforeConditionalDesc'),
|
||||
manual: gcli.lookup('jsbSpaceBeforeConditionalManual')
|
||||
},
|
||||
{
|
||||
name: 'unescapeStrings',
|
||||
type: 'boolean',
|
||||
description: gcli.lookup('jsbUnescapeStringsDesc'),
|
||||
manual: gcli.lookup('jsbUnescapeStringsManual')
|
||||
group: gcli.lookup("jsbOptionsDesc"),
|
||||
params: [
|
||||
{
|
||||
name: 'indentSize',
|
||||
type: 'number',
|
||||
description: gcli.lookup('jsbIndentSizeDesc'),
|
||||
manual: gcli.lookup('jsbIndentSizeManual'),
|
||||
defaultValue: 2
|
||||
},
|
||||
{
|
||||
name: 'indentChar',
|
||||
type: {
|
||||
name: 'selection',
|
||||
lookup: [
|
||||
{ name: "space", value: " " },
|
||||
{ name: "tab", value: "\t" }
|
||||
]
|
||||
},
|
||||
description: gcli.lookup('jsbIndentCharDesc'),
|
||||
manual: gcli.lookup('jsbIndentCharManual'),
|
||||
defaultValue: ' ',
|
||||
},
|
||||
{
|
||||
name: 'doNotPreserveNewlines',
|
||||
type: 'boolean',
|
||||
description: gcli.lookup('jsbDoNotPreserveNewlinesDesc')
|
||||
},
|
||||
{
|
||||
name: 'preserveMaxNewlines',
|
||||
type: 'number',
|
||||
description: gcli.lookup('jsbPreserveMaxNewlinesDesc'),
|
||||
manual: gcli.lookup('jsbPreserveMaxNewlinesManual'),
|
||||
defaultValue: -1
|
||||
},
|
||||
{
|
||||
name: 'jslintHappy',
|
||||
type: 'boolean',
|
||||
description: gcli.lookup('jsbJslintHappyDesc'),
|
||||
manual: gcli.lookup('jsbJslintHappyManual')
|
||||
},
|
||||
{
|
||||
name: 'braceStyle',
|
||||
type: {
|
||||
name: 'selection',
|
||||
data: ['collapse', 'expand', 'end-expand', 'expand-strict']
|
||||
},
|
||||
description: gcli.lookup('jsbBraceStyleDesc'),
|
||||
manual: gcli.lookup('jsbBraceStyleManual'),
|
||||
defaultValue: "collapse"
|
||||
},
|
||||
{
|
||||
name: 'noSpaceBeforeConditional',
|
||||
type: 'boolean',
|
||||
description: gcli.lookup('jsbNoSpaceBeforeConditionalDesc')
|
||||
},
|
||||
{
|
||||
name: 'unescapeStrings',
|
||||
type: 'boolean',
|
||||
description: gcli.lookup('jsbUnescapeStringsDesc'),
|
||||
manual: gcli.lookup('jsbUnescapeStringsManual')
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
exec: function(args, context) {
|
||||
let opts = {
|
||||
indent_size: args.indentSize,
|
||||
indent_char: args.indentChar,
|
||||
preserve_newlines: args.preserveNewlines,
|
||||
preserve_newlines: !args.doNotPreserveNewlines,
|
||||
max_preserve_newlines: args.preserveMaxNewlines == -1 ?
|
||||
undefined : args.preserveMaxNewlines,
|
||||
jslint_happy: args.jslintHappy,
|
||||
brace_style: args.braceStyle,
|
||||
space_before_conditional: args.spaceBeforeConditional,
|
||||
space_before_conditional: !args.noSpaceBeforeConditional,
|
||||
unescape_strings: args.unescapeStrings
|
||||
}
|
||||
};
|
||||
|
||||
let xhr = new XMLHttpRequest();
|
||||
|
||||
|
@ -117,13 +120,13 @@ gcli.addCommand({
|
|||
if (xhr.status == 200 || xhr.status == 0) {
|
||||
let browserDoc = context.environment.chromeDocument;
|
||||
let browserWindow = browserDoc.defaultView;
|
||||
let browser = browserWindow.gBrowser;
|
||||
|
||||
browser.selectedTab = browser.addTab("data:text/plain;base64," +
|
||||
browserWindow.btoa(js_beautify(xhr.responseText, opts)));
|
||||
let gBrowser = browserWindow.gBrowser;
|
||||
let result = js_beautify(xhr.responseText, opts);
|
||||
|
||||
browserWindow.Scratchpad.ScratchpadManager.openScratchpad({text: result});
|
||||
|
||||
promise.resolve();
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
promise.resolve("Unable to load page to beautify: " + args.url + " " +
|
||||
xhr.status + " " + xhr.statusText);
|
||||
}
|
||||
|
|
|
@ -34,3 +34,6 @@
|
|||
direction: ltr;
|
||||
}
|
||||
|
||||
.gcli-row-out .nowrap {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
|
|
@ -3056,7 +3056,10 @@ exports.setContents = function(elem, contents) {
|
|||
return;
|
||||
}
|
||||
|
||||
if (exports.isXmlDocument(elem.ownerDocument)) {
|
||||
if ('innerHTML' in elem) {
|
||||
elem.innerHTML = contents;
|
||||
}
|
||||
else {
|
||||
try {
|
||||
var ns = elem.ownerDocument.documentElement.namespaceURI;
|
||||
if (!ns) {
|
||||
|
@ -3076,9 +3079,6 @@ exports.setContents = function(elem, contents) {
|
|||
throw ex;
|
||||
}
|
||||
}
|
||||
else {
|
||||
elem.innerHTML = contents;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -5469,7 +5469,7 @@ function Requisition(environment, doc) {
|
|||
// The command that we are about to execute.
|
||||
// @see setCommandConversion()
|
||||
this.commandAssignment = new CommandAssignment();
|
||||
this._setAssignment(this.commandAssignment, null, true);
|
||||
this.setAssignment(this.commandAssignment, null);
|
||||
|
||||
// The object that stores of Assignment objects that we are filling out.
|
||||
// The Assignment objects are stored under their param.name for named
|
||||
|
@ -5556,7 +5556,7 @@ Requisition.prototype._commandAssignmentChanged = function(ev) {
|
|||
for (var i = 0; i < command.params.length; i++) {
|
||||
var param = command.params[i];
|
||||
var assignment = new Assignment(param, i);
|
||||
this._setAssignment(assignment, null, true);
|
||||
this.setAssignment(assignment, null);
|
||||
assignment.onAssignmentChange.add(this._assignmentChanged, this);
|
||||
this._assignments[param.name] = assignment;
|
||||
}
|
||||
|
@ -5678,27 +5678,23 @@ Requisition.prototype.getAssignments = function(includeCommand) {
|
|||
return assignments;
|
||||
};
|
||||
|
||||
/**
|
||||
* Alter the given assignment using the given arg.
|
||||
* @param assignment The assignment to alter
|
||||
* @param arg The new value for the assignment. An instance of Argument, or an
|
||||
* instance of Conversion, or null to set the blank value.
|
||||
*/
|
||||
Requisition.prototype.setAssignment = function(assignment, arg) {
|
||||
this._setAssignment(assignment, arg, false);
|
||||
};
|
||||
|
||||
/**
|
||||
* Internal function to alter the given assignment using the given arg.
|
||||
* @param assignment The assignment to alter
|
||||
* @param arg The new value for the assignment. An instance of Argument, or an
|
||||
* instance of Conversion, or null to set the blank value.
|
||||
* @param skipArgUpdate (default=false) Adjusts the args in this requisition to
|
||||
* keep things up to date. Args should only be skipped when setAssignment is
|
||||
* being called as part of the update process.
|
||||
* @param options There are a number of ways to customize how the assignment
|
||||
* is made, including:
|
||||
* - argUpdate: (default:false) Adjusts the args in this requisition to keep
|
||||
* things up to date. Args should only be skipped when setAssignment is being
|
||||
* called as part of the update process.
|
||||
* - matchPadding: (default:false) If argUpdate=true, and matchPadding=true
|
||||
* then further take the step of altering the whitespace on the prefix and
|
||||
* suffix of the new argument to match that of the old argument.
|
||||
*/
|
||||
Requisition.prototype._setAssignment = function(assignment, arg, skipArgUpdate) {
|
||||
if (!skipArgUpdate) {
|
||||
Requisition.prototype.setAssignment = function(assignment, arg, options) {
|
||||
options = options || {};
|
||||
if (options.argUpdate) {
|
||||
var originalArgs = assignment.arg.getArgs();
|
||||
|
||||
// Update the args array
|
||||
|
@ -5724,6 +5720,16 @@ Requisition.prototype._setAssignment = function(assignment, arg, skipArgUpdate)
|
|||
this._args.splice(index, 1);
|
||||
}
|
||||
else {
|
||||
if (options.matchPadding) {
|
||||
if (replacementArgs[i].prefix.length === 0 &&
|
||||
this._args[index].prefix.length !== 0) {
|
||||
replacementArgs[i].prefix = this._args[index].prefix;
|
||||
}
|
||||
if (replacementArgs[i].suffix.length === 0 &&
|
||||
this._args[index].suffix.length !== 0) {
|
||||
replacementArgs[i].suffix = this._args[index].suffix;
|
||||
}
|
||||
}
|
||||
this._args[index] = replacementArgs[i];
|
||||
}
|
||||
}
|
||||
|
@ -5761,7 +5767,7 @@ Requisition.prototype._setAssignment = function(assignment, arg, skipArgUpdate)
|
|||
*/
|
||||
Requisition.prototype.setBlankArguments = function() {
|
||||
this.getAssignments().forEach(function(assignment) {
|
||||
this._setAssignment(assignment, null, true);
|
||||
this.setAssignment(assignment, null);
|
||||
}, this);
|
||||
};
|
||||
|
||||
|
@ -5801,13 +5807,13 @@ Requisition.prototype.complete = function(cursor, predictionChoice) {
|
|||
// logic, so we don't use addSpace
|
||||
if (assignment.isInName()) {
|
||||
var newArg = assignment.conversion.arg.beget({ prefixPostSpace: true });
|
||||
this.setAssignment(assignment, newArg);
|
||||
this.setAssignment(assignment, newArg, { argUpdate: true });
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Mutate this argument to hold the completion
|
||||
var arg = assignment.arg.beget({ text: prediction.name });
|
||||
this.setAssignment(assignment, arg);
|
||||
this.setAssignment(assignment, arg, { argUpdate: true });
|
||||
|
||||
if (!prediction.incomplete) {
|
||||
// The prediction is complete, add a space to let the user move-on
|
||||
|
@ -5832,7 +5838,7 @@ Requisition.prototype.complete = function(cursor, predictionChoice) {
|
|||
Requisition.prototype._addSpace = function(assignment) {
|
||||
var arg = assignment.conversion.arg.beget({ suffixSpace: true });
|
||||
if (arg !== assignment.conversion.arg) {
|
||||
this.setAssignment(assignment, arg);
|
||||
this.setAssignment(assignment, arg, { argUpdate: true });
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -5844,7 +5850,7 @@ Requisition.prototype.decrement = function(assignment) {
|
|||
if (replacement != null) {
|
||||
var str = assignment.param.type.stringify(replacement);
|
||||
var arg = assignment.conversion.arg.beget({ text: str });
|
||||
this.setAssignment(assignment, arg);
|
||||
this.setAssignment(assignment, arg, { argUpdate: true });
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -5856,7 +5862,7 @@ Requisition.prototype.increment = function(assignment) {
|
|||
if (replacement != null) {
|
||||
var str = assignment.param.type.stringify(replacement);
|
||||
var arg = assignment.conversion.arg.beget({ text: str });
|
||||
this.setAssignment(assignment, arg);
|
||||
this.setAssignment(assignment, arg, { argUpdate: true });
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -6514,7 +6520,7 @@ Requisition.prototype._split = function(args) {
|
|||
// Special case: if the user enters { console.log('foo'); } then we need to
|
||||
// use the hidden 'eval' command
|
||||
conversion = new Conversion(evalCommand, new ScriptArgument());
|
||||
this._setAssignment(this.commandAssignment, conversion, true);
|
||||
this.setAssignment(this.commandAssignment, conversion);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -6541,7 +6547,7 @@ Requisition.prototype._split = function(args) {
|
|||
argsUsed++;
|
||||
}
|
||||
|
||||
this._setAssignment(this.commandAssignment, conversion, true);
|
||||
this.setAssignment(this.commandAssignment, conversion);
|
||||
|
||||
for (var i = 0; i < argsUsed; i++) {
|
||||
args.shift();
|
||||
|
@ -6588,7 +6594,7 @@ Requisition.prototype._assign = function(args) {
|
|||
var assignment = this.getAssignment(0);
|
||||
if (assignment.param.type instanceof StringType) {
|
||||
var arg = (args.length === 1) ? args[0] : new MergedArgument(args);
|
||||
this._setAssignment(assignment, arg, true);
|
||||
this.setAssignment(assignment, arg);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -6633,7 +6639,7 @@ Requisition.prototype._assign = function(args) {
|
|||
arrayArg.addArgument(arg);
|
||||
}
|
||||
else {
|
||||
this._setAssignment(assignment, arg, true);
|
||||
this.setAssignment(assignment, arg);
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
@ -6650,7 +6656,7 @@ Requisition.prototype._assign = function(args) {
|
|||
// If not set positionally, and we can't set it non-positionally,
|
||||
// we have to default it to prevent previous values surviving
|
||||
if (!assignment.param.isPositionalAllowed) {
|
||||
this._setAssignment(assignment, null, true);
|
||||
this.setAssignment(assignment, null);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -6667,7 +6673,7 @@ Requisition.prototype._assign = function(args) {
|
|||
}
|
||||
else {
|
||||
if (args.length === 0) {
|
||||
this._setAssignment(assignment, null, true);
|
||||
this.setAssignment(assignment, null);
|
||||
}
|
||||
else {
|
||||
var arg = args.splice(0, 1)[0];
|
||||
|
@ -6681,7 +6687,7 @@ Requisition.prototype._assign = function(args) {
|
|||
this._unassigned.push(new UnassignedAssignment(this, arg));
|
||||
}
|
||||
else {
|
||||
this._setAssignment(assignment, arg, true);
|
||||
this.setAssignment(assignment, arg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6690,7 +6696,7 @@ Requisition.prototype._assign = function(args) {
|
|||
// Now we need to assign the array argument (if any)
|
||||
Object.keys(arrayArgs).forEach(function(name) {
|
||||
var assignment = this.getAssignment(name);
|
||||
this._setAssignment(assignment, arrayArgs[name], true);
|
||||
this.setAssignment(assignment, arrayArgs[name]);
|
||||
}, this);
|
||||
|
||||
// What's left is can't be assigned, but we need to extract
|
||||
|
@ -8066,8 +8072,10 @@ JavascriptField.prototype.setConversion = function(conversion) {
|
|||
};
|
||||
|
||||
JavascriptField.prototype.itemClicked = function(ev) {
|
||||
this.onFieldChange(ev);
|
||||
this.setMessage(ev.conversion.message);
|
||||
var conversion = this.type.parse(ev.arg);
|
||||
|
||||
this.onFieldChange({ conversion: conversion });
|
||||
this.setMessage(conversion.message);
|
||||
};
|
||||
|
||||
JavascriptField.prototype.onInputChange = function(ev) {
|
||||
|
@ -8180,12 +8188,11 @@ Menu.prototype.destroy = function() {
|
|||
* @param ev The click event from the browser
|
||||
*/
|
||||
Menu.prototype.onItemClickInternal = function(ev) {
|
||||
var name = ev.currentTarget.querySelector('.gcli-menu-name').innerHTML;
|
||||
var name = ev.currentTarget.querySelector('.gcli-menu-name').textContent;
|
||||
var arg = new Argument(name);
|
||||
arg.suffix = ' ';
|
||||
|
||||
var conversion = this.type.parse(arg);
|
||||
this.onItemClick({ conversion: conversion });
|
||||
this.onItemClick({ arg: arg });
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -8201,7 +8208,7 @@ Menu.prototype.show = function(items, match) {
|
|||
|
||||
if (match) {
|
||||
this.items = this.items.map(function(item) {
|
||||
return gethighlightingProxy(item, match, this.template.ownerDocument);
|
||||
return getHighlightingProxy(item, match, this.template.ownerDocument);
|
||||
}.bind(this));
|
||||
}
|
||||
|
||||
|
@ -8227,7 +8234,7 @@ Menu.prototype.show = function(items, match) {
|
|||
/**
|
||||
* Create a proxy around an item that highlights matching text
|
||||
*/
|
||||
function gethighlightingProxy(item, match, document) {
|
||||
function getHighlightingProxy(item, match, document) {
|
||||
if (typeof Proxy === 'undefined') {
|
||||
return item;
|
||||
}
|
||||
|
@ -8289,12 +8296,12 @@ Menu.prototype.selectChoice = function() {
|
|||
return false;
|
||||
}
|
||||
|
||||
var name = selected.innerHTML;
|
||||
var name = selected.textContent;
|
||||
var arg = new Argument(name);
|
||||
arg.suffix = ' ';
|
||||
arg.prefix = ' ';
|
||||
|
||||
var conversion = this.type.parse(arg);
|
||||
this.onItemClick({ conversion: conversion });
|
||||
this.onItemClick({ arg: arg });
|
||||
return true;
|
||||
};
|
||||
|
||||
|
@ -8498,8 +8505,10 @@ SelectionTooltipField.prototype.setConversion = function(conversion) {
|
|||
};
|
||||
|
||||
SelectionTooltipField.prototype.itemClicked = function(ev) {
|
||||
this.onFieldChange(ev);
|
||||
this.setMessage(ev.conversion.message);
|
||||
var conversion = this.type.parse(ev.arg);
|
||||
|
||||
this.onFieldChange({ conversion: conversion });
|
||||
this.setMessage(conversion.message);
|
||||
};
|
||||
|
||||
SelectionTooltipField.prototype.onInputChange = function(ev) {
|
||||
|
@ -10340,7 +10349,8 @@ Tooltip.prototype.selectChoice = function(ev) {
|
|||
* Called by the onFieldChange event on the current Field
|
||||
*/
|
||||
Tooltip.prototype.fieldChanged = function(ev) {
|
||||
this.requisition.setAssignment(this.assignment, ev.conversion.arg);
|
||||
var options = { argUpdate: true, matchPadding: true };
|
||||
this.requisition.setAssignment(this.assignment, ev.conversion.arg, options);
|
||||
|
||||
var isError = ev.conversion.message != null && ev.conversion.message !== '';
|
||||
this.focusManager.setError(isError);
|
||||
|
|
|
@ -6,52 +6,68 @@
|
|||
const TEST_URI = "http://example.com/browser/browser/devtools/commandline/" +
|
||||
"test/browser_cmd_jsb_script.jsi";
|
||||
|
||||
let scratchpadWin = null;
|
||||
let Scratchpad = null;
|
||||
|
||||
function test() {
|
||||
DeveloperToolbarTest.test("about:blank", [ /*GJT_test*/ ]);
|
||||
DeveloperToolbarTest.test("about:blank", [ GJT_test ]);
|
||||
}
|
||||
|
||||
function GJT_test() {
|
||||
helpers.setInput('jsb');
|
||||
helpers.check({
|
||||
input: 'jsb',
|
||||
hints: ' <url> [indentSize] [indentChar] [preserveNewlines] [preserveMaxNewlines] [jslintHappy] [braceStyle] [spaceBeforeConditional] [unescapeStrings]',
|
||||
hints: ' <url> [options]',
|
||||
markup: 'VVV',
|
||||
status: 'ERROR'
|
||||
});
|
||||
DeveloperToolbarTest.exec({ completed: false });
|
||||
|
||||
gBrowser.addTabsProgressListener({
|
||||
onProgressChange: DeveloperToolbarTest.checkCalled(function GJT_onProgressChange(aBrowser) {
|
||||
gBrowser.removeTabsProgressListener(this);
|
||||
Services.ww.registerNotification(function(aSubject, aTopic, aData) {
|
||||
if (aTopic == "domwindowopened") {
|
||||
Services.ww.unregisterNotification(arguments.callee);
|
||||
|
||||
let win = aBrowser._contentWindow;
|
||||
let uri = win.document.location.href;
|
||||
let result = win.atob(uri.replace(/.*,/, ""));
|
||||
scratchpadWin = aSubject.QueryInterface(Ci.nsIDOMWindow);
|
||||
scratchpadWin.addEventListener("load", function GDT_onLoad() {
|
||||
scratchpadWin.removeEventListener("load", GDT_onLoad, false);
|
||||
Scratchpad = scratchpadWin.Scratchpad;
|
||||
|
||||
result = result.replace(/[\r\n]]/g, "\n");
|
||||
let observer = {
|
||||
onReady: function GJT_onReady() {
|
||||
Scratchpad.removeObserver(observer);
|
||||
|
||||
let correct = "function somefunc() {\n" +
|
||||
" for (let n = 0; n < 500; n++) {\n" +
|
||||
" if (n % 2 == 1) {\n" +
|
||||
" console.log(n);\n" +
|
||||
" console.log(n + 1);\n" +
|
||||
" }\n" +
|
||||
" }\n" +
|
||||
"}";
|
||||
is(result, correct, "JS has been correctly prettified");
|
||||
})
|
||||
});
|
||||
let result = Scratchpad.getText();
|
||||
result = result.replace(/[\r\n]]*/g, "\n");
|
||||
let correct = "function somefunc() {\n" +
|
||||
" if (true) // Some comment\n" +
|
||||
" doSomething();\n" +
|
||||
" for (let n = 0; n < 500; n++) {\n" +
|
||||
" if (n % 2 == 1) {\n" +
|
||||
" console.log(n);\n" +
|
||||
" console.log(n + 1);\n" +
|
||||
" }\n" +
|
||||
" }\n" +
|
||||
"}";
|
||||
is(result, correct, "JS has been correctly prettified");
|
||||
|
||||
finishUp();
|
||||
},
|
||||
};
|
||||
Scratchpad.addObserver(observer);
|
||||
}, false);
|
||||
}
|
||||
});
|
||||
|
||||
info("Checking beautification");
|
||||
|
||||
helpers.setInput('jsb ' + TEST_URI);
|
||||
/*
|
||||
helpers.check({
|
||||
input: 'jsb',
|
||||
hints: ' [options]',
|
||||
markup: 'VVV',
|
||||
status: 'VALID'
|
||||
DeveloperToolbarTest.exec({
|
||||
typed: "jsb " + TEST_URI,
|
||||
completed: false
|
||||
});
|
||||
*/
|
||||
|
||||
DeveloperToolbarTest.exec({ completed: false });
|
||||
}
|
||||
|
||||
let finishUp = DeveloperToolbarTest.checkCalled(function GJT_finishUp() {
|
||||
if (scratchpadWin) {
|
||||
scratchpadWin.close();
|
||||
scratchpadWin = null;
|
||||
}
|
||||
});
|
||||
|
|
|
@ -1 +1,2 @@
|
|||
function somefunc(){for(let n=0;n<500;n++){if(n%2==1){console.log(n);console.log(n+1);}}}
|
||||
function somefunc(){if (true) // Some comment
|
||||
doSomething();for(let n=0;n<500;n++){if(n%2==1){console.log(n);console.log(n+1);}}}
|
||||
|
|
|
@ -1,804 +0,0 @@
|
|||
/*
|
||||
* Software License Agreement (BSD License)
|
||||
*
|
||||
* Copyright (c) 2007, Parakey Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use of this software in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above
|
||||
* copyright notice, this list of conditions and the
|
||||
* following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the
|
||||
* following disclaimer in the documentation and/or other
|
||||
* materials provided with the distribution.
|
||||
*
|
||||
* * Neither the name of Parakey Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior
|
||||
* written permission of Parakey Inc.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
|
||||
* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Creator:
|
||||
* Joe Hewitt
|
||||
* Contributors
|
||||
* John J. Barton (IBM Almaden)
|
||||
* Jan Odvarko (Mozilla Corp.)
|
||||
* Max Stepanov (Aptana Inc.)
|
||||
* Rob Campbell (Mozilla Corp.)
|
||||
* Hans Hillen (Paciello Group, Mozilla)
|
||||
* Curtis Bartley (Mozilla Corp.)
|
||||
* Mike Collins (IBM Almaden)
|
||||
* Kevin Decker
|
||||
* Mike Ratcliffe (Comartis AG)
|
||||
* Hernan Rodríguez Colmeiro
|
||||
* Austin Andrews
|
||||
* Christoph Dorn
|
||||
* Steven Roussey (AppCenter Inc, Network54)
|
||||
*/
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//// InsideOutBox
|
||||
|
||||
/**
|
||||
* InsideOutBoxView is a simple interface definition for views implementing
|
||||
* InsideOutBox controls. All implementors must define these methods.
|
||||
* Implemented in InspectorUI.
|
||||
*/
|
||||
|
||||
/*
|
||||
InsideOutBoxView = {
|
||||
//
|
||||
* Retrieves the parent object for a given child object.
|
||||
* @param aChild
|
||||
* The child node to retrieve the parent object for.
|
||||
* @returns a DOM node | null
|
||||
//
|
||||
getParentObject: function(aChild) {},
|
||||
|
||||
//
|
||||
* Retrieves a given child node.
|
||||
*
|
||||
* If both index and previousSibling are passed, the implementation
|
||||
* may assume that previousSibling will be the return for getChildObject
|
||||
* with index-1.
|
||||
* @param aParent
|
||||
* The parent object of the child object to retrieve.
|
||||
* @param aIndex
|
||||
* The index of the child object to retrieve from aParent.
|
||||
* @param aPreviousSibling
|
||||
* The previous sibling of the child object to retrieve.
|
||||
* Supercedes aIndex.
|
||||
* @returns a DOM object | null
|
||||
//
|
||||
getChildObject: function(aParent, aIndex, aPreviousSibling) {},
|
||||
|
||||
//
|
||||
* Renders the HTML representation of the object. Should return an HTML
|
||||
* object which will be displayed to the user.
|
||||
* @param aObject
|
||||
* The object to create the box object for.
|
||||
* @param aIsRoot
|
||||
* Is the object the root object. May not be used in all
|
||||
* implementations.
|
||||
* @returns an object box | null
|
||||
//
|
||||
createObjectBox: function(aObject, aIsRoot) {},
|
||||
|
||||
//
|
||||
* Convenience wrappers for classList API.
|
||||
* @param aObject
|
||||
* DOM node to query/set.
|
||||
* @param aClassName
|
||||
* String containing the class name to query/set.
|
||||
//
|
||||
hasClass: function(aObject, aClassName) {},
|
||||
addClass: function(aObject, aClassName) {},
|
||||
removeClass: function(aObject, aClassName) {}
|
||||
};
|
||||
*/
|
||||
|
||||
/**
|
||||
* Creates a tree based on objects provided by a separate "view" object.
|
||||
*
|
||||
* Construction uses an "inside-out" algorithm, meaning that the view's job is
|
||||
* first to tell us the ancestry of each object, and secondarily its
|
||||
* descendants.
|
||||
*
|
||||
* Constructor
|
||||
* @param aView
|
||||
* The view requiring the InsideOutBox.
|
||||
* @param aBox
|
||||
* The box object containing the InsideOutBox. Required to add/remove
|
||||
* children during box manipulation (toggling opened or closed).
|
||||
*/
|
||||
|
||||
var EXPORTED_SYMBOLS = ["InsideOutBox"];
|
||||
|
||||
const Cu = Components.utils;
|
||||
Cu.import("resource:///modules/devtools/LayoutHelpers.jsm");
|
||||
|
||||
function InsideOutBox(aView, aBox)
|
||||
{
|
||||
this.view = aView;
|
||||
this.box = aBox;
|
||||
|
||||
this.rootObject = null;
|
||||
|
||||
this.rootObjectBox = null;
|
||||
this.selectedObjectBox = null;
|
||||
this.highlightedObjectBox = null;
|
||||
this.scrollIntoView = false;
|
||||
};
|
||||
|
||||
InsideOutBox.prototype =
|
||||
{
|
||||
/**
|
||||
* Highlight the given object node in the tree.
|
||||
* @param aObject
|
||||
* the object to highlight.
|
||||
* @returns objectBox
|
||||
*/
|
||||
highlight: function IOBox_highlight(aObject)
|
||||
{
|
||||
let objectBox = this.createObjectBox(aObject);
|
||||
this.highlightObjectBox(objectBox);
|
||||
return objectBox;
|
||||
},
|
||||
|
||||
/**
|
||||
* Open the given object node in the tree.
|
||||
* @param aObject
|
||||
* The object node to open.
|
||||
* @returns objectBox
|
||||
*/
|
||||
openObject: function IOBox_openObject(aObject)
|
||||
{
|
||||
let object = aObject;
|
||||
let firstChild = this.view.getChildObject(object, 0);
|
||||
if (firstChild)
|
||||
object = firstChild;
|
||||
|
||||
return this.openToObject(object);
|
||||
},
|
||||
|
||||
/**
|
||||
* Open the tree up to the given object node.
|
||||
* @param aObject
|
||||
* The object in the tree to open to.
|
||||
* @returns objectBox
|
||||
*/
|
||||
openToObject: function IOBox_openToObject(aObject)
|
||||
{
|
||||
let objectBox = this.createObjectBox(aObject);
|
||||
this.openObjectBox(objectBox);
|
||||
return objectBox;
|
||||
},
|
||||
|
||||
/**
|
||||
* Select the given object node in the tree.
|
||||
* @param aObject
|
||||
* The object node to select.
|
||||
* @param makeBoxVisible
|
||||
* Boolean. Open the object box in the tree?
|
||||
* @param forceOpen
|
||||
* Force the object box open by expanding all elements in the tree?
|
||||
* @param scrollIntoView
|
||||
* Scroll the objectBox into view?
|
||||
* @returns nsIDOMNode|null
|
||||
* A DOM node that represents the "object box", the element that
|
||||
* holds/displays the given aObject representation in the tree. If
|
||||
* the object cannot be selected, if it is a stale object, null is
|
||||
* returned.
|
||||
*/
|
||||
select:
|
||||
function IOBox_select(aObject, makeBoxVisible, forceOpen, scrollIntoView)
|
||||
{
|
||||
let objectBox = this.createObjectBox(aObject);
|
||||
if (!objectBox) {
|
||||
return null;
|
||||
}
|
||||
this.selectObjectBox(objectBox, forceOpen);
|
||||
if (makeBoxVisible) {
|
||||
this.openObjectBox(objectBox);
|
||||
}
|
||||
if (scrollIntoView) {
|
||||
// We want to center the label of the element, not the whole tag
|
||||
// (which includes all of its children, and is vertically huge).
|
||||
LayoutHelpers.scrollIntoViewIfNeeded(objectBox.firstElementChild);
|
||||
}
|
||||
|
||||
return objectBox;
|
||||
},
|
||||
|
||||
/**
|
||||
* Expands/contracts the given object, depending on its state.
|
||||
* @param aObject
|
||||
* The tree node to expand/contract.
|
||||
*/
|
||||
toggleObject: function IOBox_toggleObject(aObject)
|
||||
{
|
||||
let box = this.createObjectBox(aObject);
|
||||
if (!(this.view.hasClass(box, "open")))
|
||||
this.expandObjectBox(box);
|
||||
else
|
||||
this.contractObjectBox(box);
|
||||
},
|
||||
|
||||
/**
|
||||
* Expand the given object in the tree.
|
||||
* @param aObject
|
||||
* The tree node to expand.
|
||||
*/
|
||||
expandObject: function IOBox_expandObject(aObject)
|
||||
{
|
||||
let objectBox = this.createObjectBox(aObject);
|
||||
if (objectBox)
|
||||
this.expandObjectBox(objectBox);
|
||||
},
|
||||
|
||||
/**
|
||||
* Contract the given object in the tree.
|
||||
* @param aObject
|
||||
* The tree node to contract.
|
||||
*/
|
||||
contractObject: function IOBox_contractObject(aObject)
|
||||
{
|
||||
let objectBox = this.createObjectBox(aObject);
|
||||
if (objectBox)
|
||||
this.contractObjectBox(objectBox);
|
||||
},
|
||||
|
||||
/**
|
||||
* General method for iterating over an object's ancestors and performing
|
||||
* some function.
|
||||
* @param aObject
|
||||
* The object whose ancestors we wish to iterate over.
|
||||
* @param aCallback
|
||||
* The function to call with the object as argument.
|
||||
*/
|
||||
|
||||
iterateObjectAncestors: function IOBox_iterateObjectAncesors(aObject, aCallback)
|
||||
{
|
||||
let object = aObject;
|
||||
if (!(aCallback && typeof(aCallback) == "function")) {
|
||||
this.view._log("Illegal argument in IOBox.iterateObjectAncestors");
|
||||
return;
|
||||
}
|
||||
while ((object = this.getParentObjectBox(object)))
|
||||
aCallback(object);
|
||||
},
|
||||
|
||||
/**
|
||||
* Highlight the given objectBox in the tree.
|
||||
* @param aObjectBox
|
||||
* The objectBox to highlight.
|
||||
*/
|
||||
highlightObjectBox: function IOBox_highlightObjectBox(aObjectBox)
|
||||
{
|
||||
let self = this;
|
||||
|
||||
if (!aObjectBox)
|
||||
return;
|
||||
|
||||
if (this.highlightedObjectBox) {
|
||||
this.view.removeClass(this.highlightedObjectBox, "highlighted");
|
||||
this.iterateObjectAncestors(this.highlightedObjectBox, function (box) {
|
||||
self.view.removeClass(box, "highlightOpen");
|
||||
});
|
||||
}
|
||||
|
||||
this.highlightedObjectBox = aObjectBox;
|
||||
|
||||
this.view.addClass(aObjectBox, "highlighted");
|
||||
this.iterateObjectAncestors(this.highlightedObjectBox, function (box) {
|
||||
self.view.addClass(box, "highlightOpen");
|
||||
});
|
||||
|
||||
aObjectBox.scrollIntoView(true);
|
||||
},
|
||||
|
||||
/**
|
||||
* Select the given objectBox in the tree, forcing it to be open if necessary.
|
||||
* @param aObjectBox
|
||||
* The objectBox to select.
|
||||
* @param forceOpen
|
||||
* Force the box (subtree) to be open?
|
||||
*/
|
||||
selectObjectBox: function IOBox_selectObjectBox(aObjectBox, forceOpen)
|
||||
{
|
||||
let isSelected = this.selectedObjectBox &&
|
||||
aObjectBox == this.selectedObjectBox;
|
||||
|
||||
// aObjectBox is already selected, return
|
||||
if (isSelected)
|
||||
return;
|
||||
|
||||
if (this.selectedObjectBox)
|
||||
this.view.removeClass(this.selectedObjectBox, "selected");
|
||||
|
||||
this.selectedObjectBox = aObjectBox;
|
||||
|
||||
if (aObjectBox) {
|
||||
this.view.addClass(aObjectBox, "selected");
|
||||
|
||||
// Force it open the first time it is selected
|
||||
if (forceOpen)
|
||||
this.expandObjectBox(aObjectBox, true);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns the next object box in the tree for navigation purposes.
|
||||
*/
|
||||
nextObjectBox: function IOBox_nextObjectBox(aBoxObject)
|
||||
{
|
||||
let candidate;
|
||||
let boxObject = aBoxObject || this.selectedObjectBox;
|
||||
if (!boxObject)
|
||||
return this.rootObjectBox;
|
||||
|
||||
// If expanded, return the first child.
|
||||
let isOpen = this.view.hasClass(boxObject, "open");
|
||||
let childObjectBox = this.getChildObjectBox(boxObject);
|
||||
if (isOpen && childObjectBox && childObjectBox.firstChild) {
|
||||
candidate = childObjectBox.firstChild;
|
||||
} else {
|
||||
// Otherwise we get the next available sibling.
|
||||
while (boxObject) {
|
||||
if (boxObject.nextSibling) {
|
||||
boxObject = boxObject.nextSibling;
|
||||
break;
|
||||
}
|
||||
boxObject = this.getParentObjectBox(boxObject);
|
||||
}
|
||||
candidate = boxObject;
|
||||
}
|
||||
|
||||
// If the node is not an element (comments or text nodes), we
|
||||
// jump to the next line.
|
||||
if (candidate &&
|
||||
candidate.repObject.nodeType != candidate.repObject.ELEMENT_NODE) {
|
||||
return this.nextObjectBox(candidate);
|
||||
}
|
||||
|
||||
return candidate;
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns the next object in the tree for navigation purposes.
|
||||
*/
|
||||
nextObject: function IOBox_nextObject()
|
||||
{
|
||||
let next = this.nextObjectBox();
|
||||
return next ? next.repObject : null;
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns the object that is below the selection.
|
||||
*
|
||||
* @param aDistance Number of lines to jump.
|
||||
*/
|
||||
farNextObject: function IOBox_farPreviousProject(aDistance)
|
||||
{
|
||||
let boxObject = this.selectedObjectBox;
|
||||
while (aDistance-- > 0) {
|
||||
let newBoxObject = this.nextObjectBox(boxObject);
|
||||
if (!newBoxObject) {
|
||||
break;
|
||||
}
|
||||
boxObject = newBoxObject;
|
||||
}
|
||||
return boxObject ? boxObject.repObject : null;
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns the last visible child box of an object box.
|
||||
*/
|
||||
lastVisible: function IOBox_lastVisibleChild(aNode)
|
||||
{
|
||||
if (!this.view.hasClass(aNode, "open"))
|
||||
return aNode;
|
||||
|
||||
let childBox = this.getChildObjectBox(aNode);
|
||||
if (!childBox || !childBox.lastChild)
|
||||
return aNode;
|
||||
|
||||
return this.lastVisible(childBox.lastChild);
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns the previous object box in the tree for navigation purposes.
|
||||
*/
|
||||
previousObjectBox: function IOBox_previousObjectBox(aBoxObject)
|
||||
{
|
||||
let boxObject = aBoxObject || this.selectedObjectBox;
|
||||
if (!boxObject)
|
||||
return this.rootObjectBox;
|
||||
|
||||
let candidate;
|
||||
let sibling = boxObject.previousSibling;
|
||||
if (sibling) {
|
||||
candidate = this.lastVisible(sibling);
|
||||
} else {
|
||||
candidate = this.getParentObjectBox(boxObject);
|
||||
}
|
||||
|
||||
// If the node is not an element (comments or text nodes), we
|
||||
// jump to the previous line.
|
||||
if (candidate &&
|
||||
candidate.repObject.nodeType != candidate.repObject.ELEMENT_NODE) {
|
||||
return this.previousObjectBox(candidate);
|
||||
}
|
||||
|
||||
return candidate;
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns the previous object in the tree for navigation purposes.
|
||||
*/
|
||||
previousObject: function IOBox_previousObject()
|
||||
{
|
||||
let boxObject = this.previousObjectBox();
|
||||
return boxObject ? boxObject.repObject : null;
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns the object that is above the selection.
|
||||
*
|
||||
* @param aDistance Number of lines to jump.
|
||||
*/
|
||||
farPreviousObject: function IOBox_farPreviousProject(aDistance)
|
||||
{
|
||||
let boxObject = this.selectedObjectBox;
|
||||
while (aDistance-- > 0) {
|
||||
let newBoxObject = this.previousObjectBox(boxObject);
|
||||
if (!newBoxObject) {
|
||||
break;
|
||||
}
|
||||
boxObject = newBoxObject;
|
||||
if (boxObject === this.rootObjectBox)
|
||||
break;
|
||||
}
|
||||
return boxObject ? boxObject.repObject : null;
|
||||
},
|
||||
|
||||
/**
|
||||
* Open the ancestors of the given object box.
|
||||
* @param aObjectBox
|
||||
* The object box to open.
|
||||
*/
|
||||
openObjectBox: function IOBox_openObjectBox(aObjectBox)
|
||||
{
|
||||
if (!aObjectBox)
|
||||
return;
|
||||
|
||||
let self = this;
|
||||
this.iterateObjectAncestors(aObjectBox, function (box) {
|
||||
self.view.addClass(box, "open");
|
||||
let labelBox = box.querySelector(".nodeLabelBox");
|
||||
if (labelBox)
|
||||
labelBox.setAttribute("aria-expanded", "true");
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Expand the given object box.
|
||||
* @param aObjectBox
|
||||
* The object box to expand.
|
||||
*/
|
||||
expandObjectBox: function IOBox_expandObjectBox(aObjectBox)
|
||||
{
|
||||
let nodeChildBox = this.getChildObjectBox(aObjectBox);
|
||||
|
||||
// no children means nothing to expand, return
|
||||
if (!nodeChildBox)
|
||||
return;
|
||||
|
||||
if (!aObjectBox.populated) {
|
||||
let firstChild = this.view.getChildObject(aObjectBox.repObject, 0);
|
||||
this.populateChildBox(firstChild, nodeChildBox);
|
||||
}
|
||||
let labelBox = aObjectBox.querySelector(".nodeLabelBox");
|
||||
if (labelBox)
|
||||
labelBox.setAttribute("aria-expanded", "true");
|
||||
this.view.addClass(aObjectBox, "open");
|
||||
},
|
||||
|
||||
/**
|
||||
* Contract the given object box.
|
||||
* @param aObjectBox
|
||||
* The object box to contract.
|
||||
*/
|
||||
contractObjectBox: function IOBox_contractObjectBox(aObjectBox)
|
||||
{
|
||||
this.view.removeClass(aObjectBox, "open");
|
||||
let nodeLabel = aObjectBox.querySelector(".nodeLabel");
|
||||
let labelBox = nodeLabel.querySelector(".nodeLabelBox");
|
||||
if (labelBox)
|
||||
labelBox.setAttribute("aria-expanded", "false");
|
||||
},
|
||||
|
||||
/**
|
||||
* Toggle the given object box, forcing open if requested.
|
||||
* @param aObjectBox
|
||||
* The object box to toggle.
|
||||
* @param forceOpen
|
||||
* Force the objectbox open?
|
||||
*/
|
||||
toggleObjectBox: function IOBox_toggleObjectBox(aObjectBox, forceOpen)
|
||||
{
|
||||
let isOpen = this.view.hasClass(aObjectBox, "open");
|
||||
|
||||
if (!forceOpen && isOpen)
|
||||
this.contractObjectBox(aObjectBox);
|
||||
else if (!isOpen)
|
||||
this.expandObjectBox(aObjectBox);
|
||||
},
|
||||
|
||||
/**
|
||||
* Creates all of the boxes for an object, its ancestors, and siblings.
|
||||
* @param aObject
|
||||
* The tree node to create the object boxes for.
|
||||
* @returns anObjectBox or null
|
||||
*/
|
||||
createObjectBox: function IOBox_createObjectBox(aObject)
|
||||
{
|
||||
if (!aObject)
|
||||
return null;
|
||||
|
||||
this.rootObject = this.getRootNode(aObject) || aObject;
|
||||
|
||||
// Get or create all of the boxes for the target and its ancestors
|
||||
let objectBox = this.createObjectBoxes(aObject, this.rootObject);
|
||||
|
||||
if (!objectBox)
|
||||
return null;
|
||||
|
||||
if (aObject == this.rootObject)
|
||||
return objectBox;
|
||||
|
||||
return this.populateChildBox(aObject, objectBox.parentNode);
|
||||
},
|
||||
|
||||
/**
|
||||
* Creates all of the boxes for an object, its ancestors, and siblings up to
|
||||
* a root.
|
||||
* @param aObject
|
||||
* The tree's object node to create the object boxes for.
|
||||
* @param aRootObject
|
||||
* The root object at which to stop building object boxes.
|
||||
* @returns an object box or null
|
||||
*/
|
||||
createObjectBoxes: function IOBox_createObjectBoxes(aObject, aRootObject)
|
||||
{
|
||||
if (!aObject)
|
||||
return null;
|
||||
|
||||
if (aObject == aRootObject) {
|
||||
if (!this.rootObjectBox || this.rootObjectBox.repObject != aRootObject) {
|
||||
if (this.rootObjectBox) {
|
||||
try {
|
||||
this.box.removeChild(this.rootObjectBox);
|
||||
} catch (exc) {
|
||||
this.view._log("this.box.removeChild(this.rootObjectBox) FAILS " +
|
||||
this.box + " must not contain " + this.rootObjectBox);
|
||||
}
|
||||
}
|
||||
|
||||
this.highlightedObjectBox = null;
|
||||
this.selectedObjectBox = null;
|
||||
this.rootObjectBox = this.view.createObjectBox(aObject, true);
|
||||
this.box.appendChild(this.rootObjectBox);
|
||||
}
|
||||
return this.rootObjectBox;
|
||||
}
|
||||
|
||||
let parentNode = this.view.getParentObject(aObject);
|
||||
let parentObjectBox = this.createObjectBoxes(parentNode, aRootObject);
|
||||
|
||||
if (!parentObjectBox)
|
||||
return null;
|
||||
|
||||
let parentChildBox = this.getChildObjectBox(parentObjectBox);
|
||||
|
||||
if (!parentChildBox)
|
||||
return null;
|
||||
|
||||
let childObjectBox = this.findChildObjectBox(parentChildBox, aObject);
|
||||
|
||||
return childObjectBox ? childObjectBox
|
||||
: this.populateChildBox(aObject, parentChildBox);
|
||||
},
|
||||
|
||||
/**
|
||||
* Locate the object box for a given object node.
|
||||
* @param aObject
|
||||
* The given object node in the tree.
|
||||
* @returns an object box or null.
|
||||
*/
|
||||
findObjectBox: function IOBox_findObjectBox(aObject)
|
||||
{
|
||||
if (!aObject)
|
||||
return null;
|
||||
|
||||
if (aObject == this.rootObject)
|
||||
return this.rootObjectBox;
|
||||
|
||||
let parentNode = this.view.getParentObject(aObject);
|
||||
let parentObjectBox = this.findObjectBox(parentNode);
|
||||
if (!parentObjectBox)
|
||||
return null;
|
||||
|
||||
let parentChildBox = this.getChildObjectBox(parentObjectBox);
|
||||
if (!parentChildBox)
|
||||
return null;
|
||||
|
||||
return this.findChildObjectBox(parentChildBox, aObject);
|
||||
},
|
||||
|
||||
getAncestorByClass: function IOBox_getAncestorByClass(node, className)
|
||||
{
|
||||
for (let parent = node; parent; parent = parent.parentNode) {
|
||||
if (this.view.hasClass(parent, className))
|
||||
return parent;
|
||||
}
|
||||
|
||||
return null;
|
||||
},
|
||||
|
||||
/**
|
||||
* We want all children of the parent of repObject.
|
||||
*/
|
||||
populateChildBox: function IOBox_populateChildBox(repObject, nodeChildBox)
|
||||
{
|
||||
if (!repObject)
|
||||
return null;
|
||||
|
||||
let parentObjectBox = this.getAncestorByClass(nodeChildBox, "nodeBox");
|
||||
|
||||
if (parentObjectBox.populated)
|
||||
return this.findChildObjectBox(nodeChildBox, repObject);
|
||||
|
||||
let lastSiblingBox = this.getChildObjectBox(nodeChildBox);
|
||||
let siblingBox = nodeChildBox.firstChild;
|
||||
let targetBox = null;
|
||||
let view = this.view;
|
||||
let targetSibling = null;
|
||||
let parentNode = view.getParentObject(repObject);
|
||||
|
||||
for (let i = 0; 1; ++i) {
|
||||
targetSibling = view.getChildObject(parentNode, i, targetSibling);
|
||||
if (!targetSibling)
|
||||
break;
|
||||
|
||||
// Check if we need to start appending, or continue to insert before
|
||||
if (lastSiblingBox && lastSiblingBox.repObject == targetSibling)
|
||||
lastSiblingBox = null;
|
||||
|
||||
if (!siblingBox || siblingBox.repObject != targetSibling) {
|
||||
let newBox = view.createObjectBox(targetSibling);
|
||||
if (newBox) {
|
||||
if (lastSiblingBox)
|
||||
nodeChildBox.insertBefore(newBox, lastSiblingBox);
|
||||
else
|
||||
nodeChildBox.appendChild(newBox);
|
||||
}
|
||||
|
||||
siblingBox = newBox;
|
||||
}
|
||||
|
||||
if (targetSibling == repObject)
|
||||
targetBox = siblingBox;
|
||||
|
||||
if (siblingBox && siblingBox.repObject == targetSibling)
|
||||
siblingBox = siblingBox.nextSibling;
|
||||
}
|
||||
|
||||
if (targetBox)
|
||||
parentObjectBox.populated = true;
|
||||
|
||||
return targetBox;
|
||||
},
|
||||
|
||||
/**
|
||||
* Get the parent object box of a given object box.
|
||||
* @params aObjectBox
|
||||
* The object box of the parent.
|
||||
* @returns an object box or null
|
||||
*/
|
||||
getParentObjectBox: function IOBox_getParentObjectBox(aObjectBox)
|
||||
{
|
||||
let parent = aObjectBox.parentNode ? aObjectBox.parentNode.parentNode : null;
|
||||
return parent && parent.repObject ? parent : null;
|
||||
},
|
||||
|
||||
/**
|
||||
* Get the child object box of a given object box.
|
||||
* @param aObjectBox
|
||||
* The object box whose child you want.
|
||||
* @returns an object box or null
|
||||
*/
|
||||
getChildObjectBox: function IOBox_getChildObjectBox(aObjectBox)
|
||||
{
|
||||
return aObjectBox.querySelector(".nodeChildBox");
|
||||
},
|
||||
|
||||
/**
|
||||
* Find the child object box for a given repObject within the subtree
|
||||
* rooted at aParentNodeBox.
|
||||
* @param aParentNodeBox
|
||||
* root of the subtree in which to search for repObject.
|
||||
* @param aRepObject
|
||||
* The object you wish to locate in the subtree.
|
||||
* @returns an object box or null
|
||||
*/
|
||||
findChildObjectBox: function IOBox_findChildObjectBox(aParentNodeBox, aRepObject)
|
||||
{
|
||||
let childBox = aParentNodeBox.firstChild;
|
||||
while (childBox) {
|
||||
if (childBox.repObject == aRepObject)
|
||||
return childBox;
|
||||
childBox = childBox.nextSibling;
|
||||
}
|
||||
return null; // not found
|
||||
},
|
||||
|
||||
/**
|
||||
* Determines if the given node is an ancestor of the current root.
|
||||
* @param aNode
|
||||
* The node to look for within the tree.
|
||||
* @returns boolean
|
||||
*/
|
||||
isInExistingRoot: function IOBox_isInExistingRoot(aNode)
|
||||
{
|
||||
let parentNode = aNode;
|
||||
while (parentNode && parentNode != this.rootObject) {
|
||||
parentNode = this.view.getParentObject(parentNode);
|
||||
}
|
||||
return parentNode == this.rootObject;
|
||||
},
|
||||
|
||||
/**
|
||||
* Get the root node of a given node.
|
||||
* @param aNode
|
||||
* The node whose root you wish to retrieve.
|
||||
* @returns a root node or null
|
||||
*/
|
||||
getRootNode: function IOBox_getRootNode(aNode)
|
||||
{
|
||||
let node = aNode;
|
||||
let tmpNode;
|
||||
while ((tmpNode = this.view.getParentObject(node)))
|
||||
node = tmpNode;
|
||||
|
||||
return node;
|
||||
},
|
||||
|
||||
/**
|
||||
* Clean up our mess.
|
||||
*/
|
||||
destroy: function IOBox_destroy()
|
||||
{
|
||||
delete this.view;
|
||||
delete this.box;
|
||||
delete this.rootObject;
|
||||
delete this.rootObjectBox;
|
||||
delete this.selectedObjectBox;
|
||||
delete this.highlightedObjectBox;
|
||||
delete this.scrollIntoView;
|
||||
}
|
||||
};
|
|
@ -11,9 +11,6 @@ VPATH = @srcdir@
|
|||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
EXTRA_JS_MODULES = \
|
||||
domplate.jsm \
|
||||
InsideOutBox.jsm \
|
||||
TreePanel.jsm \
|
||||
highlighter.jsm \
|
||||
$(NULL)
|
||||
|
||||
|
|
|
@ -1,844 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* 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/. */
|
||||
|
||||
const Cu = Components.utils;
|
||||
const Ci = Components.interfaces;
|
||||
|
||||
Cu.import("resource:///modules/domplate.jsm");
|
||||
Cu.import("resource:///modules/InsideOutBox.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource:///modules/inspector.jsm");
|
||||
Cu.import("resource:///modules/devtools/LayoutHelpers.jsm");
|
||||
|
||||
var EXPORTED_SYMBOLS = ["TreePanel", "DOMHelpers"];
|
||||
|
||||
const INSPECTOR_URI = "chrome://browser/content/inspector.html";
|
||||
|
||||
/**
|
||||
* TreePanel
|
||||
* A container for the Inspector's HTML Tree Panel widget constructor function.
|
||||
* @param aContext nsIDOMWindow (xulwindow)
|
||||
* @param aIUI global InspectorUI object
|
||||
*/
|
||||
function TreePanel(aContext, aIUI) {
|
||||
this._init(aContext, aIUI);
|
||||
};
|
||||
|
||||
TreePanel.prototype = {
|
||||
showTextNodesWithWhitespace: false,
|
||||
id: "treepanel", // DO NOT LOCALIZE
|
||||
_open: false,
|
||||
|
||||
/**
|
||||
* The tree panel container element.
|
||||
* @returns xul:panel|xul:vbox|null
|
||||
* xul:panel is returned when the tree panel is not docked, or
|
||||
* xul:vbox when when the tree panel is docked.
|
||||
* null is returned when no container is available.
|
||||
*/
|
||||
get container()
|
||||
{
|
||||
return this.document.getElementById("inspector-tree-box");
|
||||
},
|
||||
|
||||
/**
|
||||
* Main TreePanel boot-strapping method. Initialize the TreePanel with the
|
||||
* originating context and the InspectorUI global.
|
||||
* @param aContext nsIDOMWindow (xulwindow)
|
||||
* @param aIUI global InspectorUI object
|
||||
*/
|
||||
_init: function TP__init(aContext, aIUI)
|
||||
{
|
||||
this.IUI = aIUI;
|
||||
this.window = aContext;
|
||||
this.document = this.window.document;
|
||||
this.button =
|
||||
this.IUI.chromeDoc.getElementById("inspector-treepanel-toolbutton");
|
||||
|
||||
domplateUtils.setDOM(this.window);
|
||||
|
||||
this.DOMHelpers = new DOMHelpers(this.window);
|
||||
|
||||
let isOpen = this.isOpen.bind(this);
|
||||
|
||||
this.editingEvents = {};
|
||||
},
|
||||
|
||||
/**
|
||||
* Initialization function for the TreePanel.
|
||||
*/
|
||||
initializeIFrame: function TP_initializeIFrame()
|
||||
{
|
||||
if (!this.initializingTreePanel || this.treeLoaded) {
|
||||
return;
|
||||
}
|
||||
this.treeBrowserDocument = this.treeIFrame.contentDocument;
|
||||
this.treePanelDiv = this.treeBrowserDocument.createElement("div");
|
||||
this.treeBrowserDocument.body.appendChild(this.treePanelDiv);
|
||||
this.treePanelDiv.ownerPanel = this;
|
||||
this.ioBox = new InsideOutBox(this, this.treePanelDiv);
|
||||
this.ioBox.createObjectBox(this.IUI.win.document.documentElement);
|
||||
this.treeLoaded = true;
|
||||
this._boundTreeKeyPress = this.onTreeKeyPress.bind(this);
|
||||
this.treeIFrame.addEventListener("keypress", this._boundTreeKeyPress.bind(this), true);
|
||||
this.treeIFrame.addEventListener("click", this.onTreeClick.bind(this), false);
|
||||
this.treeIFrame.addEventListener("dblclick", this.onTreeDblClick.bind(this), false);
|
||||
this.treeIFrame.focus();
|
||||
delete this.initializingTreePanel;
|
||||
Services.obs.notifyObservers(null,
|
||||
this.IUI.INSPECTOR_NOTIFICATIONS.TREEPANELREADY, null);
|
||||
if (this.pendingSelection) {
|
||||
this.select(this.pendingSelection.node, this.pendingSelection.scroll);
|
||||
delete this.pendingSelection;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Open the inspector's tree panel and initialize it.
|
||||
*/
|
||||
open: function TP_open()
|
||||
{
|
||||
if (this._open) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._open = true;
|
||||
|
||||
this.button.setAttribute("checked", true);
|
||||
this.initializingTreePanel = true;
|
||||
|
||||
this.treeIFrame = this.document.getElementById("inspector-tree-iframe");
|
||||
if (!this.treeIFrame) {
|
||||
this.treeIFrame = this.document.createElement("iframe");
|
||||
this.treeIFrame.setAttribute("id", "inspector-tree-iframe");
|
||||
this.treeIFrame.flex = 1;
|
||||
this.treeIFrame.setAttribute("type", "content");
|
||||
this.treeIFrame.setAttribute("context", "inspector-node-popup");
|
||||
}
|
||||
|
||||
let treeBox = null;
|
||||
treeBox = this.document.createElement("vbox");
|
||||
treeBox.id = "inspector-tree-box";
|
||||
treeBox.state = "open";
|
||||
try {
|
||||
treeBox.height =
|
||||
Services.prefs.getIntPref("devtools.inspector.htmlHeight");
|
||||
} catch(e) {
|
||||
treeBox.height = 112;
|
||||
}
|
||||
|
||||
treeBox.minHeight = 64;
|
||||
|
||||
this.splitter = this.document.createElement("splitter");
|
||||
this.splitter.id = "inspector-tree-splitter";
|
||||
this.splitter.className = "devtools-horizontal-splitter";
|
||||
|
||||
let container = this.document.getElementById("appcontent");
|
||||
container.appendChild(this.splitter);
|
||||
container.appendChild(treeBox);
|
||||
|
||||
treeBox.appendChild(this.treeIFrame);
|
||||
|
||||
this._boundLoadedInitializeTreePanel = function loadedInitializeTreePanel()
|
||||
{
|
||||
this.treeIFrame.removeEventListener("load",
|
||||
this._boundLoadedInitializeTreePanel, true);
|
||||
delete this._boundLoadedInitializeTreePanel;
|
||||
this.initializeIFrame();
|
||||
}.bind(this);
|
||||
|
||||
this.treeIFrame.addEventListener("load",
|
||||
this._boundLoadedInitializeTreePanel, true);
|
||||
|
||||
let src = this.treeIFrame.getAttribute("src");
|
||||
if (src != INSPECTOR_URI) {
|
||||
this.treeIFrame.setAttribute("src", INSPECTOR_URI);
|
||||
} else {
|
||||
this.treeIFrame.contentWindow.location.reload();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Close the TreePanel.
|
||||
*/
|
||||
close: function TP_close()
|
||||
{
|
||||
this._open = false;
|
||||
|
||||
// Stop caring about the tree iframe load if it's in progress.
|
||||
if (this._boundLoadedInitializeTreePanel) {
|
||||
this.treeIFrame.removeEventListener("load",
|
||||
this._boundLoadedInitializeTreePanel, true);
|
||||
delete this._boundLoadedInitializeTreePanel;
|
||||
}
|
||||
|
||||
this.button.removeAttribute("checked");
|
||||
let treeBox = this.container;
|
||||
Services.prefs.setIntPref("devtools.inspector.htmlHeight", treeBox.height);
|
||||
let treeBoxParent = treeBox.parentNode;
|
||||
treeBoxParent.removeChild(this.splitter);
|
||||
treeBoxParent.removeChild(treeBox);
|
||||
|
||||
if (this.treePanelDiv) {
|
||||
this.treePanelDiv.ownerPanel = null;
|
||||
let parent = this.treePanelDiv.parentNode;
|
||||
parent.removeChild(this.treePanelDiv);
|
||||
this.treeIFrame.removeEventListener("keypress", this._boundTreeKeyPress, true);
|
||||
delete this.treePanelDiv;
|
||||
delete this.treeBrowserDocument;
|
||||
}
|
||||
|
||||
if (this.ioBox) {
|
||||
this.ioBox.destroy();
|
||||
delete this.ioBox;
|
||||
}
|
||||
|
||||
this.treeLoaded = false;
|
||||
},
|
||||
|
||||
/**
|
||||
* Is the TreePanel open?
|
||||
* @returns boolean
|
||||
*/
|
||||
isOpen: function TP_isOpen()
|
||||
{
|
||||
return this._open;
|
||||
},
|
||||
|
||||
/**
|
||||
* Toggle the TreePanel.
|
||||
*/
|
||||
toggle: function TP_toggle()
|
||||
{
|
||||
this.isOpen() ? this.close() : this.open();
|
||||
},
|
||||
|
||||
/**
|
||||
* Create the ObjectBox for the given object.
|
||||
* @param object nsIDOMNode
|
||||
* @param isRoot boolean - Is this the root object?
|
||||
* @returns InsideOutBox
|
||||
*/
|
||||
createObjectBox: function TP_createObjectBox(object, isRoot)
|
||||
{
|
||||
let tag = domplateUtils.getNodeTag(object);
|
||||
if (tag)
|
||||
return tag.replace({object: object}, this.treeBrowserDocument);
|
||||
},
|
||||
|
||||
getParentObject: function TP_getParentObject(node)
|
||||
{
|
||||
return this.DOMHelpers.getParentObject(node);
|
||||
},
|
||||
|
||||
getChildObject: function TP_getChildObject(node, index, previousSibling)
|
||||
{
|
||||
return this.DOMHelpers.getChildObject(node, index, previousSibling,
|
||||
this.showTextNodesWithWhitespace);
|
||||
},
|
||||
|
||||
getFirstChild: function TP_getFirstChild(node)
|
||||
{
|
||||
return this.DOMHelpers.getFirstChild(node);
|
||||
},
|
||||
|
||||
getNextSibling: function TP_getNextSibling(node)
|
||||
{
|
||||
return this.DOMHelpers.getNextSibling(node);
|
||||
},
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
// Event Handling
|
||||
|
||||
/**
|
||||
* Handle click events in the html tree panel.
|
||||
* @param aEvent
|
||||
* The mouse event.
|
||||
*/
|
||||
onTreeClick: function TP_onTreeClick(aEvent)
|
||||
{
|
||||
let node;
|
||||
let target = aEvent.target;
|
||||
let hitTwisty = false;
|
||||
if (this.hasClass(target, "twisty")) {
|
||||
node = this.getRepObject(aEvent.target.nextSibling);
|
||||
hitTwisty = true;
|
||||
} else {
|
||||
node = this.getRepObject(aEvent.target);
|
||||
}
|
||||
|
||||
if (node) {
|
||||
if (hitTwisty) {
|
||||
this.ioBox.toggleObject(node);
|
||||
} else {
|
||||
if (this.IUI.inspecting) {
|
||||
this.IUI.stopInspecting(true);
|
||||
} else {
|
||||
this.navigate(node);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Handle double-click events in the html tree panel.
|
||||
* Double-clicking an attribute name or value allows it to be edited.
|
||||
* @param aEvent
|
||||
* The mouse event.
|
||||
*/
|
||||
onTreeDblClick: function TP_onTreeDblClick(aEvent)
|
||||
{
|
||||
// if already editing an attribute value, double-clicking elsewhere
|
||||
// in the tree is the same as a click, which dismisses the editor
|
||||
if (this.editingContext)
|
||||
this.closeEditor();
|
||||
|
||||
let target = aEvent.target;
|
||||
|
||||
if (!this.hasClass(target, "editable")) {
|
||||
return;
|
||||
}
|
||||
|
||||
let repObj = this.getRepObject(target);
|
||||
|
||||
if (this.hasClass(target, "nodeValue")) {
|
||||
let attrName = target.getAttribute("data-attributeName");
|
||||
let attrVal = target.innerHTML;
|
||||
|
||||
this.editAttribute(target, repObj, attrName, attrVal);
|
||||
}
|
||||
|
||||
if (this.hasClass(target, "nodeName")) {
|
||||
let attrName = target.innerHTML;
|
||||
let attrValNode = target.nextSibling.nextSibling; // skip 2 (=)
|
||||
|
||||
if (attrValNode)
|
||||
this.editAttribute(target, repObj, attrName, attrValNode.innerHTML);
|
||||
}
|
||||
},
|
||||
|
||||
navigate: function TP_navigate(node)
|
||||
{
|
||||
if (!node)
|
||||
return;
|
||||
this.ioBox.select(node, false, false, true);
|
||||
|
||||
if (this.IUI.highlighter.isNodeHighlightable(node)) {
|
||||
this.IUI.select(node, true, false, "treepanel");
|
||||
this.IUI.highlighter.highlight(node);
|
||||
}
|
||||
},
|
||||
|
||||
onTreeKeyPress: function TP_onTreeKeyPress(aEvent)
|
||||
{
|
||||
let handled = true;
|
||||
switch(aEvent.keyCode) {
|
||||
case Ci.nsIDOMKeyEvent.DOM_VK_LEFT:
|
||||
this.ioBox.contractObjectBox(this.ioBox.selectedObjectBox);
|
||||
break;
|
||||
case Ci.nsIDOMKeyEvent.DOM_VK_RIGHT:
|
||||
this.ioBox.expandObjectBox(this.ioBox.selectedObjectBox);
|
||||
break;
|
||||
case Ci.nsIDOMKeyEvent.DOM_VK_UP:
|
||||
this.navigate(this.ioBox.previousObject());
|
||||
break;
|
||||
case Ci.nsIDOMKeyEvent.DOM_VK_DOWN:
|
||||
this.navigate(this.ioBox.nextObject());
|
||||
break;
|
||||
case Ci.nsIDOMKeyEvent.DOM_VK_PAGE_UP:
|
||||
this.navigate(this.ioBox.farPreviousObject(10));
|
||||
break;
|
||||
case Ci.nsIDOMKeyEvent.DOM_VK_PAGE_DOWN:
|
||||
this.navigate(this.ioBox.farNextObject(10));
|
||||
break;
|
||||
case Ci.nsIDOMKeyEvent.DOM_VK_HOME:
|
||||
this.navigate(this.ioBox.rootObject);
|
||||
break;
|
||||
default:
|
||||
handled = false;
|
||||
}
|
||||
if (handled) {
|
||||
aEvent.stopPropagation();
|
||||
aEvent.preventDefault();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Starts the editor for an attribute name or value.
|
||||
* @param aAttrObj
|
||||
* The DOM object representing the attribute name or value in the HTML
|
||||
* Tree.
|
||||
* @param aRepObj
|
||||
* The original DOM (target) object being inspected/edited
|
||||
* @param aAttrName
|
||||
* The name of the attribute being edited
|
||||
* @param aAttrVal
|
||||
* The current value of the attribute being edited
|
||||
*/
|
||||
editAttribute:
|
||||
function TP_editAttribute(aAttrObj, aRepObj, aAttrName, aAttrVal)
|
||||
{
|
||||
let editor = this.treeBrowserDocument.getElementById("attribute-editor");
|
||||
let editorInput =
|
||||
this.treeBrowserDocument.getElementById("attribute-editor-input");
|
||||
let attrDims = aAttrObj.getBoundingClientRect();
|
||||
// figure out actual viewable viewport dimensions (sans scrollbars)
|
||||
let viewportWidth = this.treeBrowserDocument.documentElement.clientWidth;
|
||||
let viewportHeight = this.treeBrowserDocument.documentElement.clientHeight;
|
||||
|
||||
// saves the editing context for use when the editor is saved/closed
|
||||
this.editingContext = {
|
||||
attrObj: aAttrObj,
|
||||
repObj: aRepObj,
|
||||
attrName: aAttrName,
|
||||
attrValue: aAttrVal
|
||||
};
|
||||
|
||||
// highlight attribute-value node in tree while editing
|
||||
this.addClass(aAttrObj, "editingAttributeValue");
|
||||
|
||||
// show the editor
|
||||
this.addClass(editor, "editing");
|
||||
|
||||
// offset the editor below the attribute-value node being edited
|
||||
let editorVerticalOffset = 2;
|
||||
|
||||
// keep the editor comfortably within the bounds of the viewport
|
||||
let editorViewportBoundary = 5;
|
||||
|
||||
// outer editor is sized based on the <input> box inside it
|
||||
editorInput.style.width = Math.min(attrDims.width, viewportWidth -
|
||||
editorViewportBoundary) + "px";
|
||||
editorInput.style.height = Math.min(attrDims.height, viewportHeight -
|
||||
editorViewportBoundary) + "px";
|
||||
let editorDims = editor.getBoundingClientRect();
|
||||
|
||||
// calculate position for the editor according to the attribute node
|
||||
let editorLeft = attrDims.left + this.treeIFrame.contentWindow.scrollX -
|
||||
// center the editor against the attribute value
|
||||
((editorDims.width - attrDims.width) / 2);
|
||||
let editorTop = attrDims.top + this.treeIFrame.contentWindow.scrollY +
|
||||
attrDims.height + editorVerticalOffset;
|
||||
|
||||
// but, make sure the editor stays within the visible viewport
|
||||
editorLeft = Math.max(0, Math.min(
|
||||
(this.treeIFrame.contentWindow.scrollX +
|
||||
viewportWidth - editorDims.width),
|
||||
editorLeft)
|
||||
);
|
||||
editorTop = Math.max(0, Math.min(
|
||||
(this.treeIFrame.contentWindow.scrollY +
|
||||
viewportHeight - editorDims.height),
|
||||
editorTop)
|
||||
);
|
||||
|
||||
// position the editor
|
||||
editor.style.left = editorLeft + "px";
|
||||
editor.style.top = editorTop + "px";
|
||||
|
||||
// set and select the text
|
||||
if (this.hasClass(aAttrObj, "nodeValue")) {
|
||||
editorInput.value = aAttrVal;
|
||||
editorInput.select();
|
||||
} else {
|
||||
editorInput.value = aAttrName;
|
||||
editorInput.select();
|
||||
}
|
||||
|
||||
// listen for editor specific events
|
||||
this.bindEditorEvent(editor, "click", function(aEvent) {
|
||||
aEvent.stopPropagation();
|
||||
});
|
||||
this.bindEditorEvent(editor, "dblclick", function(aEvent) {
|
||||
aEvent.stopPropagation();
|
||||
});
|
||||
this.bindEditorEvent(editor, "keypress",
|
||||
this.handleEditorKeypress.bind(this));
|
||||
|
||||
// event notification
|
||||
Services.obs.notifyObservers(null, this.IUI.INSPECTOR_NOTIFICATIONS.EDITOR_OPENED,
|
||||
null);
|
||||
},
|
||||
|
||||
/**
|
||||
* Handle binding an event handler for the editor.
|
||||
* (saves the callback for easier unbinding later)
|
||||
* @param aEditor
|
||||
* The DOM object for the editor
|
||||
* @param aEventName
|
||||
* The name of the event to listen for
|
||||
* @param aEventCallback
|
||||
* The callback to bind to the event (and also to save for later
|
||||
* unbinding)
|
||||
*/
|
||||
bindEditorEvent:
|
||||
function TP_bindEditorEvent(aEditor, aEventName, aEventCallback)
|
||||
{
|
||||
this.editingEvents[aEventName] = aEventCallback;
|
||||
aEditor.addEventListener(aEventName, aEventCallback, false);
|
||||
},
|
||||
|
||||
/**
|
||||
* Handle unbinding an event handler from the editor.
|
||||
* (unbinds the previously bound and saved callback)
|
||||
* @param aEditor
|
||||
* The DOM object for the editor
|
||||
* @param aEventName
|
||||
* The name of the event being listened for
|
||||
*/
|
||||
unbindEditorEvent: function TP_unbindEditorEvent(aEditor, aEventName)
|
||||
{
|
||||
aEditor.removeEventListener(aEventName, this.editingEvents[aEventName],
|
||||
false);
|
||||
this.editingEvents[aEventName] = null;
|
||||
},
|
||||
|
||||
/**
|
||||
* Handle keypress events in the editor.
|
||||
* @param aEvent
|
||||
* The keyboard event.
|
||||
*/
|
||||
handleEditorKeypress: function TP_handleEditorKeypress(aEvent)
|
||||
{
|
||||
if (aEvent.which == this.window.KeyEvent.DOM_VK_RETURN) {
|
||||
this.saveEditor();
|
||||
aEvent.preventDefault();
|
||||
aEvent.stopPropagation();
|
||||
} else if (aEvent.keyCode == this.window.KeyEvent.DOM_VK_ESCAPE) {
|
||||
this.closeEditor();
|
||||
aEvent.preventDefault();
|
||||
aEvent.stopPropagation();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Close the editor and cleanup.
|
||||
*/
|
||||
closeEditor: function TP_closeEditor()
|
||||
{
|
||||
if (!this.treeBrowserDocument) // already closed, bug 706092
|
||||
return;
|
||||
|
||||
let editor = this.treeBrowserDocument.getElementById("attribute-editor");
|
||||
|
||||
let editorInput =
|
||||
this.treeBrowserDocument.getElementById("attribute-editor-input");
|
||||
|
||||
// remove highlight from attribute-value node in tree
|
||||
this.removeClass(this.editingContext.attrObj, "editingAttributeValue");
|
||||
|
||||
// hide editor
|
||||
this.removeClass(editor, "editing");
|
||||
|
||||
// stop listening for editor specific events
|
||||
this.unbindEditorEvent(editor, "click");
|
||||
this.unbindEditorEvent(editor, "dblclick");
|
||||
this.unbindEditorEvent(editor, "keypress");
|
||||
|
||||
// clean up after the editor
|
||||
editorInput.value = "";
|
||||
editorInput.blur();
|
||||
this.editingContext = null;
|
||||
this.editingEvents = {};
|
||||
|
||||
// event notification
|
||||
Services.obs.notifyObservers(null, this.IUI.INSPECTOR_NOTIFICATIONS.EDITOR_CLOSED,
|
||||
null);
|
||||
},
|
||||
|
||||
/**
|
||||
* Commit the edits made in the editor, then close it.
|
||||
*/
|
||||
saveEditor: function TP_saveEditor()
|
||||
{
|
||||
let editorInput =
|
||||
this.treeBrowserDocument.getElementById("attribute-editor-input");
|
||||
let dirty = false;
|
||||
|
||||
if (this.hasClass(this.editingContext.attrObj, "nodeValue")) {
|
||||
// set the new attribute value on the original target DOM element
|
||||
this.editingContext.repObj.setAttribute(this.editingContext.attrName,
|
||||
editorInput.value);
|
||||
|
||||
// update the HTML tree attribute value
|
||||
this.editingContext.attrObj.innerHTML = editorInput.value;
|
||||
dirty = true;
|
||||
}
|
||||
|
||||
if (this.hasClass(this.editingContext.attrObj, "nodeName")) {
|
||||
// remove the original attribute from the original target DOM element
|
||||
this.editingContext.repObj.removeAttribute(this.editingContext.attrName);
|
||||
|
||||
// set the new attribute value on the original target DOM element
|
||||
this.editingContext.repObj.setAttribute(editorInput.value,
|
||||
this.editingContext.attrValue);
|
||||
|
||||
// update the HTML tree attribute value
|
||||
this.editingContext.attrObj.innerHTML = editorInput.value;
|
||||
dirty = true;
|
||||
}
|
||||
|
||||
this.IUI.isDirty = dirty;
|
||||
this.IUI.nodeChanged("treepanel");
|
||||
|
||||
// event notification
|
||||
Services.obs.notifyObservers(null, this.IUI.INSPECTOR_NOTIFICATIONS.EDITOR_SAVED,
|
||||
null);
|
||||
|
||||
this.closeEditor();
|
||||
},
|
||||
|
||||
/**
|
||||
* Simple tree select method.
|
||||
* @param aNode the DOM node in the content document to select.
|
||||
* @param aScroll boolean scroll to the visible node?
|
||||
*/
|
||||
select: function TP_select(aNode, aScroll, aFrom)
|
||||
{
|
||||
if (this.ioBox) {
|
||||
this.ioBox.select(aNode, true, aFrom != "treepanel", aScroll);
|
||||
} else {
|
||||
this.pendingSelection = { node: aNode, scroll: aScroll };
|
||||
}
|
||||
},
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//// Utility functions
|
||||
|
||||
/**
|
||||
* Does the given object have a class attribute?
|
||||
* @param aNode
|
||||
* the DOM node.
|
||||
* @param aClass
|
||||
* The class string.
|
||||
* @returns boolean
|
||||
*/
|
||||
hasClass: function TP_hasClass(aNode, aClass)
|
||||
{
|
||||
if (!(aNode instanceof this.window.Element))
|
||||
return false;
|
||||
return aNode.classList.contains(aClass);
|
||||
},
|
||||
|
||||
/**
|
||||
* Add the class name to the given object.
|
||||
* @param aNode
|
||||
* the DOM node.
|
||||
* @param aClass
|
||||
* The class string.
|
||||
*/
|
||||
addClass: function TP_addClass(aNode, aClass)
|
||||
{
|
||||
if (aNode instanceof this.window.Element)
|
||||
aNode.classList.add(aClass);
|
||||
},
|
||||
|
||||
/**
|
||||
* Remove the class name from the given object
|
||||
* @param aNode
|
||||
* the DOM node.
|
||||
* @param aClass
|
||||
* The class string.
|
||||
*/
|
||||
removeClass: function TP_removeClass(aNode, aClass)
|
||||
{
|
||||
if (aNode instanceof this.window.Element)
|
||||
aNode.classList.remove(aClass);
|
||||
},
|
||||
|
||||
/**
|
||||
* Get the "repObject" from the HTML panel's domplate-constructed DOM node.
|
||||
* In this system, a "repObject" is the Object being Represented by the box
|
||||
* object. It is the "real" object that we're building our facade around.
|
||||
*
|
||||
* @param element
|
||||
* The element in the HTML panel the user clicked.
|
||||
* @returns either a real node or null
|
||||
*/
|
||||
getRepObject: function TP_getRepObject(element)
|
||||
{
|
||||
let target = null;
|
||||
for (let child = element; child; child = child.parentNode) {
|
||||
if (this.hasClass(child, "repTarget"))
|
||||
target = child;
|
||||
|
||||
if (child.repObject) {
|
||||
if (!target && this.hasClass(child.repObject, "repIgnore"))
|
||||
break;
|
||||
else
|
||||
return child.repObject;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
},
|
||||
|
||||
/**
|
||||
* Remove a node box from the tree view.
|
||||
* @param aElement
|
||||
* The DOM node to remove from the HTML IOBox.
|
||||
*/
|
||||
deleteChildBox: function TP_deleteChildBox(aElement)
|
||||
{
|
||||
let childBox = this.ioBox.findObjectBox(aElement);
|
||||
if (!childBox) {
|
||||
return;
|
||||
}
|
||||
childBox.parentNode.removeChild(childBox);
|
||||
},
|
||||
|
||||
/**
|
||||
* Destructor function. Cleanup.
|
||||
*/
|
||||
destroy: function TP_destroy()
|
||||
{
|
||||
if (this.isOpen()) {
|
||||
this.close();
|
||||
}
|
||||
|
||||
domplateUtils.setDOM(null);
|
||||
|
||||
if (this.DOMHelpers) {
|
||||
this.DOMHelpers.destroy();
|
||||
delete this.DOMHelpers;
|
||||
}
|
||||
|
||||
if (this.treePanelDiv) {
|
||||
this.treePanelDiv.ownerPanel = null;
|
||||
let parent = this.treePanelDiv.parentNode;
|
||||
parent.removeChild(this.treePanelDiv);
|
||||
delete this.treePanelDiv;
|
||||
delete this.treeBrowserDocument;
|
||||
}
|
||||
|
||||
if (this.treeIFrame) {
|
||||
this.treeIFrame.removeEventListener("dblclick", this.onTreeDblClick, false);
|
||||
this.treeIFrame.removeEventListener("click", this.onTreeClick, false);
|
||||
let parent = this.treeIFrame.parentNode;
|
||||
parent.removeChild(this.treeIFrame);
|
||||
delete this.treeIFrame;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* DOMHelpers
|
||||
* Makes DOM traversal easier. Goes through iframes.
|
||||
*
|
||||
* @constructor
|
||||
* @param nsIDOMWindow aWindow
|
||||
* The content window, owning the document to traverse.
|
||||
*/
|
||||
function DOMHelpers(aWindow) {
|
||||
this.window = aWindow;
|
||||
};
|
||||
|
||||
DOMHelpers.prototype = {
|
||||
getParentObject: function Helpers_getParentObject(node)
|
||||
{
|
||||
let parentNode = node ? node.parentNode : null;
|
||||
|
||||
if (!parentNode) {
|
||||
// Documents have no parentNode; Attr, Document, DocumentFragment, Entity,
|
||||
// and Notation. top level windows have no parentNode
|
||||
if (node && node == this.window.Node.DOCUMENT_NODE) {
|
||||
// document type
|
||||
if (node.defaultView) {
|
||||
let embeddingFrame = node.defaultView.frameElement;
|
||||
if (embeddingFrame)
|
||||
return embeddingFrame.parentNode;
|
||||
}
|
||||
}
|
||||
// a Document object without a parentNode or window
|
||||
return null; // top level has no parent
|
||||
}
|
||||
|
||||
if (parentNode.nodeType == this.window.Node.DOCUMENT_NODE) {
|
||||
if (parentNode.defaultView) {
|
||||
return parentNode.defaultView.frameElement;
|
||||
}
|
||||
// parent is document element, but no window at defaultView.
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!parentNode.localName)
|
||||
return null;
|
||||
|
||||
return parentNode;
|
||||
},
|
||||
|
||||
getChildObject: function Helpers_getChildObject(node, index, previousSibling,
|
||||
showTextNodesWithWhitespace)
|
||||
{
|
||||
if (!node)
|
||||
return null;
|
||||
|
||||
if (node.contentDocument) {
|
||||
// then the node is a frame
|
||||
if (index == 0) {
|
||||
return node.contentDocument.documentElement; // the node's HTMLElement
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
if (node instanceof this.window.GetSVGDocument) {
|
||||
let svgDocument = node.getSVGDocument();
|
||||
if (svgDocument) {
|
||||
// then the node is a frame
|
||||
if (index == 0) {
|
||||
return svgDocument.documentElement; // the node's SVGElement
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
let child = null;
|
||||
if (previousSibling) // then we are walking
|
||||
child = this.getNextSibling(previousSibling);
|
||||
else
|
||||
child = this.getFirstChild(node);
|
||||
|
||||
if (showTextNodesWithWhitespace)
|
||||
return child;
|
||||
|
||||
for (; child; child = this.getNextSibling(child)) {
|
||||
if (!this.isWhitespaceText(child))
|
||||
return child;
|
||||
}
|
||||
|
||||
return null; // we have no children worth showing.
|
||||
},
|
||||
|
||||
getFirstChild: function Helpers_getFirstChild(node)
|
||||
{
|
||||
let SHOW_ALL = Components.interfaces.nsIDOMNodeFilter.SHOW_ALL;
|
||||
this.treeWalker = node.ownerDocument.createTreeWalker(node,
|
||||
SHOW_ALL, null, false);
|
||||
return this.treeWalker.firstChild();
|
||||
},
|
||||
|
||||
getNextSibling: function Helpers_getNextSibling(node)
|
||||
{
|
||||
let next = this.treeWalker.nextSibling();
|
||||
|
||||
if (!next)
|
||||
delete this.treeWalker;
|
||||
|
||||
return next;
|
||||
},
|
||||
|
||||
isWhitespaceText: function Helpers_isWhitespaceText(node)
|
||||
{
|
||||
return node.nodeType == this.window.Node.TEXT_NODE &&
|
||||
!/[^\s]/.exec(node.nodeValue);
|
||||
},
|
||||
|
||||
destroy: function Helpers_destroy()
|
||||
{
|
||||
delete this.window;
|
||||
delete this.treeWalker;
|
||||
}
|
||||
};
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -1,18 +0,0 @@
|
|||
<!-- 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/. -->
|
||||
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
|
||||
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
|
||||
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
|
||||
<link rel="stylesheet" href="chrome://browser/skin/devtools/htmlpanel.css" type="text/css"/>
|
||||
</head>
|
||||
<body role="application">
|
||||
<div id="attribute-editor">
|
||||
<input id="attribute-editor-input" />
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -13,12 +13,12 @@ var EXPORTED_SYMBOLS = ["InspectorUI"];
|
|||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource:///modules/TreePanel.jsm");
|
||||
Cu.import("resource:///modules/devtools/MarkupView.jsm");
|
||||
Cu.import("resource:///modules/highlighter.jsm");
|
||||
Cu.import("resource:///modules/devtools/LayoutView.jsm");
|
||||
Cu.import("resource:///modules/devtools/LayoutHelpers.jsm");
|
||||
Cu.import("resource:///modules/devtools/EventEmitter.jsm");
|
||||
Cu.import("resource:///modules/devtools/DOMHelpers.jsm");
|
||||
|
||||
// Inspector notifications dispatched through the nsIObserverService.
|
||||
const INSPECTOR_NOTIFICATIONS = {
|
||||
|
|
|
@ -3,11 +3,9 @@
|
|||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
browser.jar:
|
||||
content/browser/inspector.html (highlighter/inspector.html)
|
||||
content/browser/devtools/markup-view.xhtml (markupview/markup-view.xhtml)
|
||||
content/browser/devtools/markup-view.css (markupview/markup-view.css)
|
||||
content/browser/NetworkPanel.xhtml (webconsole/NetworkPanel.xhtml)
|
||||
content/browser/devtools/HUDService-content.js (webconsole/HUDService-content.js)
|
||||
content/browser/devtools/webconsole.js (webconsole/webconsole.js)
|
||||
* content/browser/devtools/webconsole.xul (webconsole/webconsole.xul)
|
||||
* content/browser/scratchpad.xul (scratchpad/scratchpad.xul)
|
||||
|
|
|
@ -129,6 +129,8 @@ LayoutView.prototype = {
|
|||
this.iframe.removeEventListener("keypress", this.bound_handleKeypress, true);
|
||||
this.inspector.chromeWindow.removeEventListener("message", this.onMessage, true);
|
||||
this.close();
|
||||
this.sizeHeadingLabel = null;
|
||||
this.sizeLabel = null;
|
||||
this.iframe = null;
|
||||
this.view.parentNode.removeChild(this.view);
|
||||
},
|
||||
|
@ -159,6 +161,10 @@ LayoutView.prototype = {
|
|||
this.documentReady = true;
|
||||
this.doc = this.iframe.contentDocument;
|
||||
|
||||
// Save reference to the labels displaying size of the node.
|
||||
this.sizeLabel = this.doc.querySelector(".size > span");
|
||||
this.sizeHeadingLabel = this.doc.getElementById("element-size");
|
||||
|
||||
// We can't do that earlier because open() and close() need to do stuff
|
||||
// inside the iframe.
|
||||
|
||||
|
@ -299,10 +305,9 @@ LayoutView.prototype = {
|
|||
let width = Math.round(clientRect.width);
|
||||
let height = Math.round(clientRect.height);
|
||||
|
||||
let elt = this.doc.querySelector("#element-size");
|
||||
let newLabel = width + "x" + height;
|
||||
if (elt.textContent != newLabel) {
|
||||
elt.textContent = newLabel;
|
||||
if (this.sizeHeadingLabel.textContent != newLabel) {
|
||||
this.sizeHeadingLabel.textContent = newLabel;
|
||||
}
|
||||
|
||||
// If the view is closed, no need to do anything more.
|
||||
|
@ -312,7 +317,6 @@ LayoutView.prototype = {
|
|||
let style = this.browser.contentWindow.getComputedStyle(node);;
|
||||
|
||||
for (let i in this.map) {
|
||||
let selector = this.map[i].selector;
|
||||
let property = this.map[i].property;
|
||||
this.map[i].value = parseInt(style.getPropertyValue(property));
|
||||
}
|
||||
|
@ -326,6 +330,10 @@ LayoutView.prototype = {
|
|||
for (let i in this.map) {
|
||||
let selector = this.map[i].selector;
|
||||
let span = this.doc.querySelector(selector);
|
||||
if (span.textContent.length > 0 &&
|
||||
span.textContent == this.map[i].value) {
|
||||
continue;
|
||||
}
|
||||
span.textContent = this.map[i].value;
|
||||
}
|
||||
|
||||
|
@ -335,7 +343,10 @@ LayoutView.prototype = {
|
|||
height -= this.map.borderTop.value + this.map.borderBottom.value +
|
||||
this.map.paddingTop.value + this.map.paddingBottom.value;
|
||||
|
||||
this.doc.querySelector(".size > span").textContent = width + "x" + height;
|
||||
let newValue = width + "x" + height;
|
||||
if (this.sizeLabel.textContent != newValue) {
|
||||
this.sizeLabel.textContent = newValue;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
|
|
|
@ -10,6 +10,7 @@ const Cu = Components.utils;
|
|||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource:///modules/devtools/FloatingScrollbars.jsm");
|
||||
Cu.import("resource:///modules/devtools/EventEmitter.jsm");
|
||||
|
||||
var EXPORTED_SYMBOLS = ["ResponsiveUIManager"];
|
||||
|
||||
|
@ -67,6 +68,13 @@ let ResponsiveUIManager = {
|
|||
default:
|
||||
}
|
||||
},
|
||||
|
||||
get events() {
|
||||
if (!this._eventEmitter) {
|
||||
this._eventEmitter = new EventEmitter();
|
||||
}
|
||||
return this._eventEmitter;
|
||||
},
|
||||
}
|
||||
|
||||
let presets = [
|
||||
|
@ -162,6 +170,7 @@ function ResponsiveUI(aWindow, aTab)
|
|||
} catch(e) {}
|
||||
|
||||
switchToFloatingScrollbars(this.tab);
|
||||
ResponsiveUIManager.events.emit("on", this.tab, this);
|
||||
}
|
||||
|
||||
ResponsiveUI.prototype = {
|
||||
|
@ -215,6 +224,7 @@ ResponsiveUI.prototype = {
|
|||
this.stack.removeAttribute("responsivemode");
|
||||
|
||||
delete this.tab.__responsiveUI;
|
||||
ResponsiveUIManager.events.emit("off", this.tab, this);
|
||||
},
|
||||
|
||||
/**
|
||||
|
|
|
@ -45,15 +45,23 @@ include $(DEPTH)/config/autoconf.mk
|
|||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
_BROWSER_FILES = \
|
||||
browser_responsiveui.js \
|
||||
browser_responsiveruleview.js \
|
||||
browser_responsive_cmd.js \
|
||||
browser_responsivecomputedview.js \
|
||||
browser_responsiveuiaddcustompreset.js \
|
||||
head.js \
|
||||
helpers.js \
|
||||
$(NULL)
|
||||
|
||||
# Disabled on Mac for frequent intermittent failures
|
||||
ifneq ($(OS_ARCH), Darwin)
|
||||
_BROWSER_FILES += \
|
||||
browser_responsiveui.js \
|
||||
browser_responsiveuiaddcustompreset.js \
|
||||
$(NULL)
|
||||
else
|
||||
$(warning browser_responsiveui.js is disabled on OS X for intermittent failures. Bug 798772) \
|
||||
$(warning browser_responsiveuiaddcustompreset.js is disabled on OS X for intermittent failures. Bugs 798775, 798777)
|
||||
endif
|
||||
|
||||
libs:: $(_BROWSER_FILES)
|
||||
$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/browser/$(relativesrcdir)
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
function test() {
|
||||
let instance, widthBeforeClose, heightBeforeClose;
|
||||
let events = ResponsiveUI.ResponsiveUIManager.events;
|
||||
|
||||
waitForExplicitFinish();
|
||||
|
||||
|
@ -16,8 +17,8 @@ function test() {
|
|||
|
||||
function startTest() {
|
||||
document.getElementById("Tools:ResponsiveUI").removeAttribute("disabled");
|
||||
events.once("on", function() {executeSoon(onUIOpen)});
|
||||
synthesizeKeyFromKeyTag("key_responsiveUI");
|
||||
executeSoon(onUIOpen);
|
||||
}
|
||||
|
||||
function onUIOpen() {
|
||||
|
@ -118,14 +119,13 @@ function test() {
|
|||
widthBeforeClose = content.innerWidth;
|
||||
heightBeforeClose = content.innerHeight;
|
||||
|
||||
events.once("off", function() {executeSoon(restart)});
|
||||
EventUtils.synthesizeKey("VK_ESCAPE", {});
|
||||
|
||||
executeSoon(restart);
|
||||
}
|
||||
|
||||
function restart() {
|
||||
events.once("on", function() {executeSoon(onUIOpen2)});
|
||||
synthesizeKeyFromKeyTag("key_responsiveUI");
|
||||
executeSoon(onUIOpen2);
|
||||
}
|
||||
|
||||
function onUIOpen2() {
|
||||
|
@ -138,8 +138,8 @@ function test() {
|
|||
is(content.innerWidth, widthBeforeClose, "width restored.");
|
||||
is(content.innerHeight, heightBeforeClose, "height restored.");
|
||||
|
||||
events.once("off", function() {executeSoon(finishUp)});
|
||||
EventUtils.synthesizeKey("VK_ESCAPE", {});
|
||||
executeSoon(finishUp);
|
||||
}
|
||||
|
||||
function finishUp() {
|
||||
|
|
|
@ -0,0 +1,124 @@
|
|||
/* 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/. */
|
||||
|
||||
const EXPORTED_SYMBOLS = ["DOMHelpers"];
|
||||
|
||||
/**
|
||||
* DOMHelpers
|
||||
* Makes DOM traversal easier. Goes through iframes.
|
||||
*
|
||||
* @constructor
|
||||
* @param nsIDOMWindow aWindow
|
||||
* The content window, owning the document to traverse.
|
||||
*/
|
||||
function DOMHelpers(aWindow) {
|
||||
this.window = aWindow;
|
||||
};
|
||||
|
||||
DOMHelpers.prototype = {
|
||||
getParentObject: function Helpers_getParentObject(node)
|
||||
{
|
||||
let parentNode = node ? node.parentNode : null;
|
||||
|
||||
if (!parentNode) {
|
||||
// Documents have no parentNode; Attr, Document, DocumentFragment, Entity,
|
||||
// and Notation. top level windows have no parentNode
|
||||
if (node && node == this.window.Node.DOCUMENT_NODE) {
|
||||
// document type
|
||||
if (node.defaultView) {
|
||||
let embeddingFrame = node.defaultView.frameElement;
|
||||
if (embeddingFrame)
|
||||
return embeddingFrame.parentNode;
|
||||
}
|
||||
}
|
||||
// a Document object without a parentNode or window
|
||||
return null; // top level has no parent
|
||||
}
|
||||
|
||||
if (parentNode.nodeType == this.window.Node.DOCUMENT_NODE) {
|
||||
if (parentNode.defaultView) {
|
||||
return parentNode.defaultView.frameElement;
|
||||
}
|
||||
// parent is document element, but no window at defaultView.
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!parentNode.localName)
|
||||
return null;
|
||||
|
||||
return parentNode;
|
||||
},
|
||||
|
||||
getChildObject: function Helpers_getChildObject(node, index, previousSibling,
|
||||
showTextNodesWithWhitespace)
|
||||
{
|
||||
if (!node)
|
||||
return null;
|
||||
|
||||
if (node.contentDocument) {
|
||||
// then the node is a frame
|
||||
if (index == 0) {
|
||||
return node.contentDocument.documentElement; // the node's HTMLElement
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
if (node instanceof this.window.GetSVGDocument) {
|
||||
let svgDocument = node.getSVGDocument();
|
||||
if (svgDocument) {
|
||||
// then the node is a frame
|
||||
if (index == 0) {
|
||||
return svgDocument.documentElement; // the node's SVGElement
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
let child = null;
|
||||
if (previousSibling) // then we are walking
|
||||
child = this.getNextSibling(previousSibling);
|
||||
else
|
||||
child = this.getFirstChild(node);
|
||||
|
||||
if (showTextNodesWithWhitespace)
|
||||
return child;
|
||||
|
||||
for (; child; child = this.getNextSibling(child)) {
|
||||
if (!this.isWhitespaceText(child))
|
||||
return child;
|
||||
}
|
||||
|
||||
return null; // we have no children worth showing.
|
||||
},
|
||||
|
||||
getFirstChild: function Helpers_getFirstChild(node)
|
||||
{
|
||||
let SHOW_ALL = Components.interfaces.nsIDOMNodeFilter.SHOW_ALL;
|
||||
this.treeWalker = node.ownerDocument.createTreeWalker(node,
|
||||
SHOW_ALL, null, false);
|
||||
return this.treeWalker.firstChild();
|
||||
},
|
||||
|
||||
getNextSibling: function Helpers_getNextSibling(node)
|
||||
{
|
||||
let next = this.treeWalker.nextSibling();
|
||||
|
||||
if (!next)
|
||||
delete this.treeWalker;
|
||||
|
||||
return next;
|
||||
},
|
||||
|
||||
isWhitespaceText: function Helpers_isWhitespaceText(node)
|
||||
{
|
||||
return node.nodeType == this.window.Node.TEXT_NODE &&
|
||||
!/[^\s]/.exec(node.nodeValue);
|
||||
},
|
||||
|
||||
destroy: function Helpers_destroy()
|
||||
{
|
||||
delete this.window;
|
||||
delete this.treeWalker;
|
||||
}
|
||||
};
|
|
@ -7,9 +7,7 @@
|
|||
const EXPORTED_SYMBOLS = [ "DeveloperToolbar" ];
|
||||
|
||||
const NS_XHTML = "http://www.w3.org/1999/xhtml";
|
||||
|
||||
const WEBCONSOLE_CONTENT_SCRIPT_URL =
|
||||
"chrome://browser/content/devtools/HUDService-content.js";
|
||||
const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
|
||||
|
||||
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Components.utils.import("resource://gre/modules/Services.jsm");
|
||||
|
@ -26,6 +24,9 @@ XPCOMUtils.defineLazyModuleGetter(this, "gcli",
|
|||
XPCOMUtils.defineLazyModuleGetter(this, "CmdCommands",
|
||||
"resource:///modules/devtools/CmdCmd.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "PageErrorListener",
|
||||
"resource://gre/modules/devtools/WebConsoleUtils.jsm");
|
||||
|
||||
/**
|
||||
* Due to a number of panel bugs we need a way to check if we are running on
|
||||
* Linux. See the comments for TooltipPanel and OutputPanel for further details.
|
||||
|
@ -56,7 +57,8 @@ function DeveloperToolbar(aChromeWindow, aToolbarElement)
|
|||
this._lastState = NOTIFICATIONS.HIDE;
|
||||
this._pendingShowCallback = undefined;
|
||||
this._pendingHide = false;
|
||||
this._errorsCount = {};
|
||||
this._errorsCount = Object.create(null);
|
||||
this._errorListeners = Object.create(null);
|
||||
this._webConsoleButton = this._doc
|
||||
.getElementById("developer-toolbar-webconsole");
|
||||
|
||||
|
@ -88,9 +90,6 @@ const NOTIFICATIONS = {
|
|||
*/
|
||||
DeveloperToolbar.prototype.NOTIFICATIONS = NOTIFICATIONS;
|
||||
|
||||
DeveloperToolbar.prototype._contentMessageListeners =
|
||||
["WebConsole:CachedMessages", "WebConsole:PageError"];
|
||||
|
||||
/**
|
||||
* Is the toolbar open?
|
||||
*/
|
||||
|
@ -285,21 +284,18 @@ DeveloperToolbar.prototype._initErrorsCount = function DT__initErrorsCount(aTab)
|
|||
return;
|
||||
}
|
||||
|
||||
let messageManager = aTab.linkedBrowser.messageManager;
|
||||
messageManager.loadFrameScript(WEBCONSOLE_CONTENT_SCRIPT_URL, true);
|
||||
let window = aTab.linkedBrowser.contentWindow;
|
||||
let listener = new PageErrorListener(window, {
|
||||
onPageError: this._onPageError.bind(this, tabId),
|
||||
});
|
||||
listener.init();
|
||||
|
||||
this._errorListeners[tabId] = listener;
|
||||
this._errorsCount[tabId] = 0;
|
||||
|
||||
this._contentMessageListeners.forEach(function(aName) {
|
||||
messageManager.addMessageListener(aName, this);
|
||||
}, this);
|
||||
let messages = listener.getCachedMessages();
|
||||
messages.forEach(this._onPageError.bind(this, tabId));
|
||||
|
||||
let message = {
|
||||
features: ["PageError"],
|
||||
cachedMessages: ["PageError"],
|
||||
};
|
||||
|
||||
this.sendMessageToTab(aTab, "WebConsole:Init", message);
|
||||
this._updateErrorsCount();
|
||||
};
|
||||
|
||||
|
@ -319,14 +315,10 @@ DeveloperToolbar.prototype._stopErrorsCount = function DT__stopErrorsCount(aTab)
|
|||
return;
|
||||
}
|
||||
|
||||
this.sendMessageToTab(aTab, "WebConsole:Destroy", {});
|
||||
|
||||
let messageManager = aTab.linkedBrowser.messageManager;
|
||||
this._contentMessageListeners.forEach(function(aName) {
|
||||
messageManager.removeMessageListener(aName, this);
|
||||
}, this);
|
||||
|
||||
this._errorListeners[tabId].destroy();
|
||||
delete this._errorListeners[tabId];
|
||||
delete this._errorsCount[tabId];
|
||||
|
||||
this._updateErrorsCount();
|
||||
};
|
||||
|
||||
|
@ -434,61 +426,13 @@ DeveloperToolbar.prototype.handleEvent = function DT_handleEvent(aEvent)
|
|||
};
|
||||
|
||||
/**
|
||||
* The handler of messages received from the nsIMessageManager.
|
||||
*
|
||||
* @param object aMessage the message received from the content process.
|
||||
*/
|
||||
DeveloperToolbar.prototype.receiveMessage = function DT_receiveMessage(aMessage)
|
||||
{
|
||||
if (!aMessage.json || !(aMessage.json.hudId in this._errorsCount)) {
|
||||
return;
|
||||
}
|
||||
|
||||
let tabId = aMessage.json.hudId;
|
||||
let errors = this._errorsCount[tabId];
|
||||
|
||||
switch (aMessage.name) {
|
||||
case "WebConsole:PageError":
|
||||
this._onPageError(tabId, aMessage.json.pageError);
|
||||
break;
|
||||
case "WebConsole:CachedMessages":
|
||||
aMessage.json.messages.forEach(this._onPageError.bind(this, tabId));
|
||||
break;
|
||||
}
|
||||
|
||||
if (errors != this._errorsCount[tabId]) {
|
||||
this._updateErrorsCount(tabId);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Send a message to the content process using the nsIMessageManager of the
|
||||
* given tab.
|
||||
*
|
||||
* @param nsIDOMNode aTab the tab you want to send a message to.
|
||||
* @param string aName the name of the message you want to send.
|
||||
* @param object aMessage the message to send.
|
||||
*/
|
||||
DeveloperToolbar.prototype.sendMessageToTab =
|
||||
function DT_sendMessageToTab(aTab, aName, aMessage)
|
||||
{
|
||||
let tabId = aTab.linkedPanel;
|
||||
aMessage.hudId = tabId;
|
||||
if (!("id" in aMessage)) {
|
||||
aMessage.id = "DevToolbar-" + this.sequenceId;
|
||||
}
|
||||
|
||||
aTab.linkedBrowser.messageManager.sendAsyncMessage(aName, aMessage);
|
||||
};
|
||||
|
||||
/**
|
||||
* Process a "WebConsole:PageError" message received from the given tab. This
|
||||
* method counts the JavaScript exceptions received.
|
||||
* Count a page error received for the currently selected tab. This
|
||||
* method counts the JavaScript exceptions received and CSS errors/warnings.
|
||||
*
|
||||
* @private
|
||||
* @param string aTabId the ID of the tab from where the page error comes.
|
||||
* @param object aPageError the page error object received from the content
|
||||
* process.
|
||||
* @param object aPageError the page error object received from the
|
||||
* PageErrorListener.
|
||||
*/
|
||||
DeveloperToolbar.prototype._onPageError =
|
||||
function DT__onPageError(aTabId, aPageError)
|
||||
|
@ -501,6 +445,7 @@ function DT__onPageError(aTabId, aPageError)
|
|||
}
|
||||
|
||||
this._errorsCount[aTabId]++;
|
||||
this._updateErrorsCount(aTabId);
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -638,7 +583,6 @@ function OutputPanel(aChromeDoc, aInput, aLoadCallback)
|
|||
this._frame = aChromeDoc.createElementNS(NS_XHTML, "iframe");
|
||||
this._frame.id = "gcli-output-frame";
|
||||
this._frame.setAttribute("src", "chrome://browser/content/devtools/commandlineoutput.xhtml");
|
||||
this._frame.setAttribute("flex", "1");
|
||||
this._panel.appendChild(this._frame);
|
||||
|
||||
this.displayedOutput = undefined;
|
||||
|
@ -674,6 +618,33 @@ OutputPanel.prototype._onload = function OP_onload()
|
|||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Determine the scrollbar width in the current document.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
Object.defineProperty(OutputPanel.prototype, 'scrollbarWidth', {
|
||||
get: function() {
|
||||
if (this.__scrollbarWidth) {
|
||||
return this.__scrollbarWidth;
|
||||
}
|
||||
|
||||
let hbox = this.document.createElementNS(XUL_NS, "hbox");
|
||||
hbox.setAttribute("style", "height: 0%; overflow: hidden");
|
||||
|
||||
let scrollbar = this.document.createElementNS(XUL_NS, "scrollbar");
|
||||
scrollbar.setAttribute("orient", "vertical");
|
||||
hbox.appendChild(scrollbar);
|
||||
|
||||
this.document.documentElement.appendChild(hbox);
|
||||
this.__scrollbarWidth = scrollbar.clientWidth;
|
||||
this.document.documentElement.removeChild(hbox);
|
||||
|
||||
return this.__scrollbarWidth;
|
||||
},
|
||||
enumerable: true
|
||||
});
|
||||
|
||||
/**
|
||||
* Prevent the popup from hiding if it is not permitted via this.canHide.
|
||||
*/
|
||||
|
@ -691,17 +662,15 @@ OutputPanel.prototype._onpopuphiding = function OP_onpopuphiding(aEvent)
|
|||
*/
|
||||
OutputPanel.prototype.show = function OP_show()
|
||||
{
|
||||
// This is nasty, but displaying the panel causes it to re-flow, which can
|
||||
// change the size it should be, so we need to resize the iframe after the
|
||||
// panel has displayed
|
||||
this._panel.ownerDocument.defaultView.setTimeout(function() {
|
||||
this._resize();
|
||||
}.bind(this), 0);
|
||||
|
||||
if (isLinux) {
|
||||
this.canHide = false;
|
||||
}
|
||||
|
||||
// We need to reset the iframe size in order for future size calculations to
|
||||
// be correct
|
||||
this._frame.style.minHeight = this._frame.style.maxHeight = 0;
|
||||
this._frame.style.minWidth = 0;
|
||||
|
||||
this._panel.openPopup(this._input, "before_start", 0, 0, false, false, null);
|
||||
this._resize();
|
||||
|
||||
|
@ -718,8 +687,38 @@ OutputPanel.prototype._resize = function CLP_resize()
|
|||
return
|
||||
}
|
||||
|
||||
this._frame.height = this.document.body.scrollHeight;
|
||||
this._frame.width = this._input.clientWidth + 2;
|
||||
// Set max panel width to match any content with a max of the width of the
|
||||
// browser window.
|
||||
let maxWidth = this._panel.ownerDocument.documentElement.clientWidth;
|
||||
let width = Math.min(maxWidth, this.document.documentElement.scrollWidth);
|
||||
|
||||
// Add scrollbar width to content size in case a scrollbar is needed.
|
||||
width += this.scrollbarWidth;
|
||||
|
||||
// Set the width of the iframe.
|
||||
this._frame.style.minWidth = width + "px";
|
||||
|
||||
// browserAdjustment is used to correct the panel height according to the
|
||||
// browsers borders etc.
|
||||
const browserAdjustment = 15;
|
||||
|
||||
// Set max panel height to match any content with a max of the height of the
|
||||
// browser window.
|
||||
let maxHeight =
|
||||
this._panel.ownerDocument.documentElement.clientHeight - browserAdjustment;
|
||||
let height = Math.min(maxHeight, this.document.documentElement.scrollHeight);
|
||||
|
||||
// Set the height of the iframe. Setting iframe.height does not work.
|
||||
this._frame.style.minHeight = this._frame.style.maxHeight = height + "px";
|
||||
|
||||
// Set the height and width of the panel to match the iframe.
|
||||
this._panel.sizeTo(width, height);
|
||||
|
||||
// Move the panel to the correct position in the case that it has been
|
||||
// positioned incorrectly.
|
||||
let screenX = this._input.boxObject.screenX;
|
||||
let screenY = this._toolbar.boxObject.screenY;
|
||||
this._panel.moveTo(screenX, screenY - height);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -47,8 +47,11 @@ function test() {
|
|||
|
||||
function addErrors() {
|
||||
expectUncaughtException();
|
||||
let button = content.document.querySelector("button");
|
||||
EventUtils.synthesizeMouse(button, 2, 2, {}, content);
|
||||
|
||||
waitForFocus(function() {
|
||||
let button = content.document.querySelector("button");
|
||||
EventUtils.synthesizeMouse(button, 2, 2, {}, content);
|
||||
}, content);
|
||||
|
||||
waitForValue({
|
||||
name: "button shows one more error after click in page",
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -18,12 +18,10 @@ XPCOMUtils.defineLazyModuleGetter(this, "Services",
|
|||
"resource://gre/modules/Services.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "WebConsoleUtils",
|
||||
"resource:///modules/WebConsoleUtils.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "l10n", function() {
|
||||
return WebConsoleUtils.l10n;
|
||||
});
|
||||
"resource://gre/modules/devtools/WebConsoleUtils.jsm");
|
||||
|
||||
const STRINGS_URI = "chrome://browser/locale/devtools/webconsole.properties";
|
||||
let l10n = new WebConsoleUtils.l10n(STRINGS_URI);
|
||||
|
||||
var EXPORTED_SYMBOLS = ["HUDService"];
|
||||
|
||||
|
@ -59,9 +57,6 @@ const MINIMUM_PAGE_HEIGHT = 50;
|
|||
// The default console height, as a ratio from the content window inner height.
|
||||
const DEFAULT_CONSOLE_HEIGHT = 0.33;
|
||||
|
||||
// This script is inserted into the content process.
|
||||
const CONTENT_SCRIPT_URL = "chrome://browser/content/devtools/HUDService-content.js";
|
||||
|
||||
// points to the file to load in the Web Console iframe.
|
||||
const UI_IFRAME_URL = "chrome://browser/content/devtools/webconsole.xul";
|
||||
|
||||
|
@ -172,7 +167,10 @@ HUD_SERVICE.prototype =
|
|||
let hud = this.getHudReferenceById(hudId);
|
||||
let document = hud.chromeDocument;
|
||||
|
||||
hud.destroy();
|
||||
hud.destroy(function() {
|
||||
let id = WebConsoleUtils.supportsString(hudId);
|
||||
Services.obs.notifyObservers(id, "web-console-destroyed", null);
|
||||
});
|
||||
|
||||
delete this.hudReferences[hudId];
|
||||
|
||||
|
@ -199,9 +197,6 @@ HUD_SERVICE.prototype =
|
|||
contentWindow.focus();
|
||||
|
||||
HeadsUpDisplayUICommands.refreshCommand();
|
||||
|
||||
let id = WebConsoleUtils.supportsString(hudId);
|
||||
Services.obs.notifyObservers(id, "web-console-destroyed", null);
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -502,9 +497,11 @@ HUD_SERVICE.prototype =
|
|||
function WebConsole(aTab)
|
||||
{
|
||||
this.tab = aTab;
|
||||
this.chromeDocument = this.tab.ownerDocument;
|
||||
this.chromeWindow = this.chromeDocument.defaultView;
|
||||
this.hudId = "hud_" + this.tab.linkedPanel;
|
||||
this._onIframeLoad = this._onIframeLoad.bind(this);
|
||||
this._asyncRequests = {};
|
||||
this._init();
|
||||
this._initUI();
|
||||
}
|
||||
|
||||
WebConsole.prototype = {
|
||||
|
@ -514,6 +511,9 @@ WebConsole.prototype = {
|
|||
*/
|
||||
tab: null,
|
||||
|
||||
chromeWindow: null,
|
||||
chromeDocument: null,
|
||||
|
||||
/**
|
||||
* Getter for HUDService.lastFinishedRequestCallback.
|
||||
*
|
||||
|
@ -522,41 +522,12 @@ WebConsole.prototype = {
|
|||
*/
|
||||
get lastFinishedRequestCallback() HUDService.lastFinishedRequestCallback,
|
||||
|
||||
/**
|
||||
* Track callback functions registered for specific async requests sent to
|
||||
* the content process.
|
||||
*
|
||||
* @private
|
||||
* @type object
|
||||
*/
|
||||
_asyncRequests: null,
|
||||
|
||||
/**
|
||||
* Message names that the HUD listens for. These messages come from the remote
|
||||
* Web Console content script.
|
||||
*
|
||||
* @private
|
||||
* @type array
|
||||
*/
|
||||
_messageListeners: ["JSTerm:EvalObject", "WebConsole:ConsoleAPI",
|
||||
"WebConsole:CachedMessages", "WebConsole:PageError", "JSTerm:EvalResult",
|
||||
"JSTerm:AutocompleteProperties", "JSTerm:ClearOutput",
|
||||
"JSTerm:InspectObject", "WebConsole:NetworkActivity",
|
||||
"WebConsole:FileActivity", "WebConsole:LocationChange",
|
||||
"JSTerm:NonNativeConsoleAPI"],
|
||||
|
||||
/**
|
||||
* The xul:panel that holds the Web Console when it is positioned as a window.
|
||||
* @type nsIDOMElement
|
||||
*/
|
||||
consolePanel: null,
|
||||
|
||||
/**
|
||||
* The current tab location.
|
||||
* @type string
|
||||
*/
|
||||
contentLocation: "",
|
||||
|
||||
/**
|
||||
* Getter for the xul:popupset that holds any popups we open.
|
||||
* @type nsIDOMElement
|
||||
|
@ -577,22 +548,6 @@ WebConsole.prototype = {
|
|||
|
||||
get gViewSourceUtils() this.chromeWindow.gViewSourceUtils,
|
||||
|
||||
/**
|
||||
* Initialize the Web Console instance.
|
||||
* @private
|
||||
*/
|
||||
_init: function WC__init()
|
||||
{
|
||||
this.chromeDocument = this.tab.ownerDocument;
|
||||
this.chromeWindow = this.chromeDocument.defaultView;
|
||||
this.messageManager = this.tab.linkedBrowser.messageManager;
|
||||
this.hudId = "hud_" + this.tab.linkedPanel;
|
||||
this.notificationBox = this.chromeDocument
|
||||
.getElementById(this.tab.linkedPanel);
|
||||
|
||||
this._initUI();
|
||||
},
|
||||
|
||||
/**
|
||||
* Initialize the Web Console UI. This method sets up the iframe.
|
||||
* @private
|
||||
|
@ -627,7 +582,6 @@ WebConsole.prototype = {
|
|||
|
||||
this.iframeWindow = this.iframe.contentWindow.wrappedJSObject;
|
||||
this.ui = new this.iframeWindow.WebConsoleFrame(this, position);
|
||||
this._setupMessageManager();
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -772,8 +726,8 @@ WebConsole.prototype = {
|
|||
*/
|
||||
getPanelTitle: function WC_getPanelTitle()
|
||||
{
|
||||
return l10n.getFormatStr("webConsoleWindowTitleAndURL",
|
||||
[this.contentLocation]);
|
||||
let url = this.ui ? this.ui.contentLocation : "";
|
||||
return l10n.getFormatStr("webConsoleWindowTitleAndURL", [url]);
|
||||
},
|
||||
|
||||
positions: {
|
||||
|
@ -806,7 +760,7 @@ WebConsole.prototype = {
|
|||
|
||||
// get the node position index
|
||||
let nodeIdx = this.positions[aPosition];
|
||||
let nBox = this.notificationBox;
|
||||
let nBox = this.chromeDocument.getElementById(this.tab.linkedPanel);
|
||||
let node = nBox.childNodes[nodeIdx];
|
||||
|
||||
// check to see if console is already positioned in aPosition
|
||||
|
@ -903,126 +857,24 @@ WebConsole.prototype = {
|
|||
|
||||
/**
|
||||
* The clear output button handler.
|
||||
* @private
|
||||
*/
|
||||
onClearButton: function WC_onClearButton()
|
||||
_onClearButton: function WC__onClearButton()
|
||||
{
|
||||
this.ui.jsterm.clearOutput(true);
|
||||
this.chromeWindow.DeveloperToolbar.resetErrorsCount(this.tab);
|
||||
},
|
||||
|
||||
/**
|
||||
* Setup the message manager used to communicate with the Web Console content
|
||||
* script. This method loads the content script, adds the message listeners
|
||||
* and initializes the connection to the content script.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
_setupMessageManager: function WC__setupMessageManager()
|
||||
{
|
||||
this.messageManager.loadFrameScript(CONTENT_SCRIPT_URL, true);
|
||||
|
||||
this._messageListeners.forEach(function(aName) {
|
||||
this.messageManager.addMessageListener(aName, this.ui);
|
||||
}, this);
|
||||
|
||||
let message = {
|
||||
features: ["ConsoleAPI", "JSTerm", "PageError", "NetworkMonitor",
|
||||
"LocationChange"],
|
||||
cachedMessages: ["ConsoleAPI", "PageError"],
|
||||
NetworkMonitor: { monitorFileActivity: true },
|
||||
JSTerm: { notifyNonNativeConsoleAPI: true },
|
||||
preferences: {
|
||||
"NetworkMonitor.saveRequestAndResponseBodies":
|
||||
this.ui.saveRequestAndResponseBodies,
|
||||
},
|
||||
};
|
||||
|
||||
this.sendMessageToContent("WebConsole:Init", message);
|
||||
},
|
||||
|
||||
/**
|
||||
* Callback method for when the Web Console initialization is complete. For
|
||||
* now this method sends the web-console-created notification using the
|
||||
* nsIObserverService.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
_onInitComplete: function WC__onInitComplete()
|
||||
{
|
||||
let id = WebConsoleUtils.supportsString(this.hudId);
|
||||
Services.obs.notifyObservers(id, "web-console-created", null);
|
||||
},
|
||||
|
||||
/**
|
||||
* Handler for messages that have an associated callback function. The
|
||||
* this.sendMessageToContent() allows one to provide a function to be invoked
|
||||
* when the content script replies to the message previously sent. This is the
|
||||
* method that invokes the callback.
|
||||
*
|
||||
* @see this.sendMessageToContent
|
||||
* @private
|
||||
* @param object aResponse
|
||||
* Message object received from the content script.
|
||||
*/
|
||||
_receiveMessageWithCallback:
|
||||
function WC__receiveMessageWithCallback(aResponse)
|
||||
{
|
||||
if (aResponse.id in this._asyncRequests) {
|
||||
let request = this._asyncRequests[aResponse.id];
|
||||
request.callback(aResponse, request.message);
|
||||
delete this._asyncRequests[aResponse.id];
|
||||
}
|
||||
else {
|
||||
Cu.reportError("receiveMessageWithCallback response for stale request " +
|
||||
"ID " + aResponse.id);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Send a message to the content script.
|
||||
*
|
||||
* @param string aName
|
||||
* The name of the message you want to send.
|
||||
*
|
||||
* @param object aMessage
|
||||
* The message object you want to send. This object needs to have no
|
||||
* cyclic references and it needs to be JSON-stringifiable.
|
||||
*
|
||||
* @param function [aCallback]
|
||||
* Optional function you want to have called when the content script
|
||||
* replies to your message. Your callback receives two arguments:
|
||||
* (1) the response object from the content script and (2) the message
|
||||
* you sent to the content script (which is aMessage here).
|
||||
*/
|
||||
sendMessageToContent:
|
||||
function WC_sendMessageToContent(aName, aMessage, aCallback)
|
||||
{
|
||||
aMessage.hudId = this.hudId;
|
||||
if (!("id" in aMessage)) {
|
||||
aMessage.id = "HUDChrome-" + HUDService.sequenceId();
|
||||
}
|
||||
|
||||
if (aCallback) {
|
||||
this._asyncRequests[aMessage.id] = {
|
||||
name: aName,
|
||||
message: aMessage,
|
||||
callback: aCallback,
|
||||
};
|
||||
}
|
||||
this.messageManager.sendAsyncMessage(aName, aMessage);
|
||||
},
|
||||
|
||||
/**
|
||||
* Handler for the "WebConsole:LocationChange" message. If the Web Console is
|
||||
* Handler for page location changes. If the Web Console is
|
||||
* opened in a panel the panel title is updated.
|
||||
*
|
||||
* @param object aMessage
|
||||
* The message received from the content script. It needs to hold two
|
||||
* properties: location and title.
|
||||
* @param string aURI
|
||||
* New page location.
|
||||
* @param string aTitle
|
||||
* New page title.
|
||||
*/
|
||||
onLocationChange: function WC_onLocationChange(aMessage)
|
||||
onLocationChange: function WC_onLocationChange(aURI, aTitle)
|
||||
{
|
||||
this.contentLocation = aMessage.location;
|
||||
if (this.consolePanel) {
|
||||
this.consolePanel.label = this.getPanelTitle();
|
||||
}
|
||||
|
@ -1051,15 +903,13 @@ WebConsole.prototype = {
|
|||
/**
|
||||
* Destroy the object. Call this method to avoid memory leaks when the Web
|
||||
* Console is closed.
|
||||
*
|
||||
* @param function [aOnDestroy]
|
||||
* Optional function to invoke when the Web Console instance is
|
||||
* destroyed.
|
||||
*/
|
||||
destroy: function WC_destroy()
|
||||
destroy: function WC_destroy(aOnDestroy)
|
||||
{
|
||||
this.sendMessageToContent("WebConsole:Destroy", {});
|
||||
|
||||
this._messageListeners.forEach(function(aName) {
|
||||
this.messageManager.removeMessageListener(aName, this.ui);
|
||||
}, this);
|
||||
|
||||
// Make sure that the console panel does not try to call
|
||||
// deactivateHUDForContext() again.
|
||||
this.consoleWindowUnregisterOnHide = false;
|
||||
|
@ -1072,24 +922,31 @@ WebConsole.prototype = {
|
|||
}
|
||||
}
|
||||
|
||||
let onDestroy = function WC_onDestroyUI() {
|
||||
// Remove the iframe and the consolePanel if the Web Console is inside a
|
||||
// floating panel.
|
||||
if (this.consolePanel && this.consolePanel.parentNode) {
|
||||
this.consolePanel.hidePopup();
|
||||
this.consolePanel.parentNode.removeChild(this.consolePanel);
|
||||
this.consolePanel = null;
|
||||
}
|
||||
|
||||
if (this.iframe.parentNode) {
|
||||
this.iframe.parentNode.removeChild(this.iframe);
|
||||
}
|
||||
|
||||
if (this.splitter.parentNode) {
|
||||
this.splitter.parentNode.removeChild(this.splitter);
|
||||
}
|
||||
|
||||
aOnDestroy && aOnDestroy();
|
||||
}.bind(this);
|
||||
|
||||
if (this.ui) {
|
||||
this.ui.destroy();
|
||||
this.ui.destroy(onDestroy);
|
||||
}
|
||||
|
||||
// Remove the iframe and the consolePanel if the Web Console is inside a
|
||||
// floating panel.
|
||||
if (this.consolePanel && this.consolePanel.parentNode) {
|
||||
this.consolePanel.hidePopup();
|
||||
this.consolePanel.parentNode.removeChild(this.consolePanel);
|
||||
this.consolePanel = null;
|
||||
}
|
||||
|
||||
if (this.iframe.parentNode) {
|
||||
this.iframe.parentNode.removeChild(this.iframe);
|
||||
}
|
||||
|
||||
if (this.splitter.parentNode) {
|
||||
this.splitter.parentNode.removeChild(this.splitter);
|
||||
else {
|
||||
onDestroy();
|
||||
}
|
||||
},
|
||||
};
|
||||
|
|
|
@ -13,10 +13,8 @@ include $(DEPTH)/config/autoconf.mk
|
|||
EXTRA_JS_MODULES = \
|
||||
HUDService.jsm \
|
||||
PropertyPanel.jsm \
|
||||
NetworkHelper.jsm \
|
||||
NetworkPanel.jsm \
|
||||
AutocompletePopup.jsm \
|
||||
WebConsoleUtils.jsm \
|
||||
$(NULL)
|
||||
|
||||
TEST_DIRS = test
|
||||
|
|
|
@ -16,17 +16,16 @@ XPCOMUtils.defineLazyServiceGetter(this, "mimeService", "@mozilla.org/mime;1",
|
|||
"nsIMIMEService");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "NetworkHelper",
|
||||
"resource:///modules/NetworkHelper.jsm");
|
||||
"resource://gre/modules/devtools/NetworkHelper.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "NetUtil",
|
||||
"resource://gre/modules/NetUtil.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "WebConsoleUtils",
|
||||
"resource:///modules/WebConsoleUtils.jsm");
|
||||
"resource://gre/modules/devtools/WebConsoleUtils.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "l10n", function() {
|
||||
return WebConsoleUtils.l10n;
|
||||
});
|
||||
const STRINGS_URI = "chrome://browser/locale/devtools/webconsole.properties";
|
||||
let l10n = new WebConsoleUtils.l10n(STRINGS_URI);
|
||||
|
||||
var EXPORTED_SYMBOLS = ["NetworkPanel"];
|
||||
|
||||
|
@ -67,7 +66,6 @@ function NetworkPanel(aParent, aHttpActivity)
|
|||
self.panel.parentNode.removeChild(self.panel);
|
||||
self.panel = null;
|
||||
self.iframe = null;
|
||||
self.document = null;
|
||||
self.httpActivity = null;
|
||||
|
||||
if (self.linkNode) {
|
||||
|
@ -77,9 +75,17 @@ function NetworkPanel(aParent, aHttpActivity)
|
|||
}, false);
|
||||
|
||||
// Set the document object and update the content once the panel is loaded.
|
||||
this.panel.addEventListener("load", function onLoad() {
|
||||
self.panel.removeEventListener("load", onLoad, true);
|
||||
self.document = self.iframe.contentWindow.document;
|
||||
this.iframe.addEventListener("load", function onLoad() {
|
||||
if (!self.iframe) {
|
||||
return;
|
||||
}
|
||||
|
||||
self.iframe.removeEventListener("load", onLoad, true);
|
||||
self.update();
|
||||
}, true);
|
||||
|
||||
this.panel.addEventListener("popupshown", function onPopupShown() {
|
||||
self.panel.removeEventListener("popupshown", onPopupShown, true);
|
||||
self.update();
|
||||
}, true);
|
||||
|
||||
|
@ -95,12 +101,6 @@ function NetworkPanel(aParent, aHttpActivity)
|
|||
|
||||
NetworkPanel.prototype =
|
||||
{
|
||||
/**
|
||||
* Callback is called once the NetworkPanel is processed completely. Used by
|
||||
* unit tests.
|
||||
*/
|
||||
isDoneCallback: null,
|
||||
|
||||
/**
|
||||
* The current state of the output.
|
||||
*/
|
||||
|
@ -119,6 +119,20 @@ NetworkPanel.prototype =
|
|||
|
||||
_contentType: null,
|
||||
|
||||
/**
|
||||
* Function callback invoked whenever the panel content is updated. This is
|
||||
* used only by tests.
|
||||
*
|
||||
* @private
|
||||
* @type function
|
||||
*/
|
||||
_onUpdate: null,
|
||||
|
||||
get document() {
|
||||
return this.iframe && this.iframe.contentWindow ?
|
||||
this.iframe.contentWindow.document : null;
|
||||
},
|
||||
|
||||
/**
|
||||
* Small helper function that is nearly equal to l10n.getFormatStr
|
||||
* except that it prefixes aName with "NetworkPanel.".
|
||||
|
@ -151,9 +165,8 @@ NetworkPanel.prototype =
|
|||
return this._contentType;
|
||||
}
|
||||
|
||||
let entry = this.httpActivity.log.entries[0];
|
||||
let request = entry.request;
|
||||
let response = entry.response;
|
||||
let request = this.httpActivity.request;
|
||||
let response = this.httpActivity.response;
|
||||
|
||||
let contentType = "";
|
||||
let types = response.content ?
|
||||
|
@ -237,7 +250,7 @@ NetworkPanel.prototype =
|
|||
*/
|
||||
get _isResponseCached()
|
||||
{
|
||||
return this.httpActivity.log.entries[0].response.status == 304;
|
||||
return this.httpActivity.response.status == 304;
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -248,7 +261,7 @@ NetworkPanel.prototype =
|
|||
*/
|
||||
get _isRequestBodyFormData()
|
||||
{
|
||||
let requestBody = this.httpActivity.log.entries[0].request.postData.text;
|
||||
let requestBody = this.httpActivity.request.postData.text;
|
||||
return this._fromDataRegExp.test(requestBody);
|
||||
},
|
||||
|
||||
|
@ -342,9 +355,8 @@ NetworkPanel.prototype =
|
|||
*/
|
||||
_displayRequestHeader: function NP__displayRequestHeader()
|
||||
{
|
||||
let entry = this.httpActivity.log.entries[0];
|
||||
let request = entry.request;
|
||||
let requestTime = new Date(entry.startedDateTime);
|
||||
let request = this.httpActivity.request;
|
||||
let requestTime = new Date(this.httpActivity.startedDateTime);
|
||||
|
||||
this._appendTextNode("headUrl", request.url);
|
||||
this._appendTextNode("headMethod", request.method);
|
||||
|
@ -365,8 +377,9 @@ NetworkPanel.prototype =
|
|||
*
|
||||
* @returns void
|
||||
*/
|
||||
_displayRequestBody: function NP__displayRequestBody() {
|
||||
let postData = this.httpActivity.log.entries[0].request.postData;
|
||||
_displayRequestBody: function NP__displayRequestBody()
|
||||
{
|
||||
let postData = this.httpActivity.request.postData;
|
||||
this._displayNode("requestBody");
|
||||
this._appendTextNode("requestBodyContent", postData.text);
|
||||
},
|
||||
|
@ -377,8 +390,9 @@ NetworkPanel.prototype =
|
|||
*
|
||||
* @returns void
|
||||
*/
|
||||
_displayRequestForm: function NP__processRequestForm() {
|
||||
let postData = this.httpActivity.log.entries[0].request.postData.text;
|
||||
_displayRequestForm: function NP__processRequestForm()
|
||||
{
|
||||
let postData = this.httpActivity.request.postData.text;
|
||||
let requestBodyLines = postData.split("\n");
|
||||
let formData = requestBodyLines[requestBodyLines.length - 1].
|
||||
replace(/\+/g, " ").split("&");
|
||||
|
@ -418,9 +432,8 @@ NetworkPanel.prototype =
|
|||
*/
|
||||
_displayResponseHeader: function NP__displayResponseHeader()
|
||||
{
|
||||
let entry = this.httpActivity.log.entries[0];
|
||||
let timing = entry.timings;
|
||||
let response = entry.response;
|
||||
let timing = this.httpActivity.timings;
|
||||
let response = this.httpActivity.response;
|
||||
|
||||
this._appendTextNode("headStatus",
|
||||
[response.httpVersion, response.status,
|
||||
|
@ -454,16 +467,16 @@ NetworkPanel.prototype =
|
|||
_displayResponseImage: function NP__displayResponseImage()
|
||||
{
|
||||
let self = this;
|
||||
let entry = this.httpActivity.log.entries[0];
|
||||
let timing = entry.timings;
|
||||
let request = entry.request;
|
||||
let timing = this.httpActivity.timings;
|
||||
let request = this.httpActivity.request;
|
||||
let cached = "";
|
||||
|
||||
if (this._isResponseCached) {
|
||||
cached = "Cached";
|
||||
}
|
||||
|
||||
let imageNode = this.document.getElementById("responseImage" + cached +"Node");
|
||||
let imageNode = this.document.getElementById("responseImage" +
|
||||
cached + "Node");
|
||||
imageNode.setAttribute("src", request.url);
|
||||
|
||||
// This function is called to set the imageInfo.
|
||||
|
@ -499,9 +512,8 @@ NetworkPanel.prototype =
|
|||
*/
|
||||
_displayResponseBody: function NP__displayResponseBody()
|
||||
{
|
||||
let entry = this.httpActivity.log.entries[0];
|
||||
let timing = entry.timings;
|
||||
let response = entry.response;
|
||||
let timing = this.httpActivity.timings;
|
||||
let response = this.httpActivity.response;
|
||||
let cached = this._isResponseCached ? "Cached" : "";
|
||||
|
||||
this._appendTextNode("responseBody" + cached + "Info",
|
||||
|
@ -520,7 +532,7 @@ NetworkPanel.prototype =
|
|||
*/
|
||||
_displayResponseBodyUnknownType: function NP__displayResponseBodyUnknownType()
|
||||
{
|
||||
let timing = this.httpActivity.log.entries[0].timings;
|
||||
let timing = this.httpActivity.timings;
|
||||
|
||||
this._displayNode("responseBodyUnknownType");
|
||||
this._appendTextNode("responseBodyUnknownTypeInfo",
|
||||
|
@ -538,7 +550,7 @@ NetworkPanel.prototype =
|
|||
*/
|
||||
_displayNoResponseBody: function NP_displayNoResponseBody()
|
||||
{
|
||||
let timing = this.httpActivity.log.entries[0].timings;
|
||||
let timing = this.httpActivity.timings;
|
||||
|
||||
this._displayNode("responseNoBody");
|
||||
this._appendTextNode("responseNoBodyInfo",
|
||||
|
@ -554,15 +566,14 @@ NetworkPanel.prototype =
|
|||
{
|
||||
// After the iframe's contentWindow is ready, the document object is set.
|
||||
// If the document object is not available yet nothing needs to be updated.
|
||||
if (!this.document) {
|
||||
if (!this.document || !this.document.getElementById("headUrl")) {
|
||||
return;
|
||||
}
|
||||
|
||||
let stages = this.httpActivity.meta.stages;
|
||||
let entry = this.httpActivity.log.entries[0];
|
||||
let timing = entry.timings;
|
||||
let request = entry.request;
|
||||
let response = entry.response;
|
||||
let updates = this.httpActivity.updates;
|
||||
let timing = this.httpActivity.timings;
|
||||
let request = this.httpActivity.request;
|
||||
let response = this.httpActivity.response;
|
||||
|
||||
switch (this._state) {
|
||||
case this._INIT:
|
||||
|
@ -572,7 +583,7 @@ NetworkPanel.prototype =
|
|||
|
||||
case this._DISPLAYED_REQUEST_HEADER:
|
||||
// Process the request body if there is one.
|
||||
if (!this.httpActivity.meta.discardRequestBody && request.postData) {
|
||||
if (!this.httpActivity.discardRequestBody && request.postData.text) {
|
||||
// Check if we send some form data. If so, display the form data special.
|
||||
if (this._isRequestBodyFormData) {
|
||||
this._displayRequestForm();
|
||||
|
@ -585,9 +596,6 @@ NetworkPanel.prototype =
|
|||
// FALL THROUGH
|
||||
|
||||
case this._DISPLAYED_REQUEST_BODY:
|
||||
// There is always a response header. Therefore we can skip here if
|
||||
// we don't have a response header yet and don't have to try updating
|
||||
// anything else in the NetworkPanel.
|
||||
if (!response.headers.length || !Object.keys(timing).length) {
|
||||
break;
|
||||
}
|
||||
|
@ -596,13 +604,13 @@ NetworkPanel.prototype =
|
|||
// FALL THROUGH
|
||||
|
||||
case this._DISPLAYED_RESPONSE_HEADER:
|
||||
if (stages.indexOf("REQUEST_STOP") == -1 ||
|
||||
stages.indexOf("TRANSACTION_CLOSE") == -1) {
|
||||
if (updates.indexOf("responseContent") == -1 ||
|
||||
updates.indexOf("eventTimings") == -1) {
|
||||
break;
|
||||
}
|
||||
|
||||
this._state = this._TRANSITION_CLOSED;
|
||||
if (this.httpActivity.meta.discardResponseBody) {
|
||||
if (this.httpActivity.discardResponseBody) {
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -618,9 +626,12 @@ NetworkPanel.prototype =
|
|||
else if (response.content.text) {
|
||||
this._displayResponseBody();
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (this._onUpdate) {
|
||||
this._onUpdate();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ const Cu = Components.utils;
|
|||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "WebConsoleUtils",
|
||||
"resource:///modules/WebConsoleUtils.jsm");
|
||||
"resource://gre/modules/devtools/WebConsoleUtils.jsm");
|
||||
|
||||
var EXPORTED_SYMBOLS = ["PropertyPanel", "PropertyTreeView"];
|
||||
|
||||
|
@ -27,7 +27,7 @@ var EXPORTED_SYMBOLS = ["PropertyPanel", "PropertyTreeView"];
|
|||
*/
|
||||
var PropertyTreeView = function() {
|
||||
this._rows = [];
|
||||
this._objectCache = {};
|
||||
this._objectActors = [];
|
||||
};
|
||||
|
||||
PropertyTreeView.prototype = {
|
||||
|
@ -44,10 +44,24 @@ PropertyTreeView.prototype = {
|
|||
_treeBox: null,
|
||||
|
||||
/**
|
||||
* Stores cached information about local objects being inspected.
|
||||
* Track known object actor IDs. We clean these when the panel is
|
||||
* destroyed/cleaned up.
|
||||
*
|
||||
* @private
|
||||
* @type array
|
||||
*/
|
||||
_objectCache: null,
|
||||
_objectActors: null,
|
||||
|
||||
/**
|
||||
* Map fake object actors to their IDs. This is used when we inspect local
|
||||
* objects.
|
||||
* @private
|
||||
* @type Object
|
||||
*/
|
||||
_localObjectActors: null,
|
||||
|
||||
_releaseObject: null,
|
||||
_objectPropertiesProvider: null,
|
||||
|
||||
/**
|
||||
* Use this setter to update the content of the tree.
|
||||
|
@ -58,54 +72,47 @@ PropertyTreeView.prototype = {
|
|||
* - 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:
|
||||
* - objectProperties:
|
||||
* 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:
|
||||
* remote object. See WebConsoleUtils.inspectObject() for details.
|
||||
* - objectPropertiesProvider:
|
||||
* 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.
|
||||
* - actorID:
|
||||
* The object actor ID from which we request the properties.
|
||||
* - 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.
|
||||
* received. This function takes one argument: the array of
|
||||
* descriptors for each property in the object represented by the
|
||||
* actor.
|
||||
* - releaseObject:
|
||||
* Function to invoke when an object actor should be released. The
|
||||
* function must take one argument: the object actor ID.
|
||||
*/
|
||||
set data(aData) {
|
||||
let oldLen = this._rows.length;
|
||||
|
||||
this._cleanup();
|
||||
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);
|
||||
if (aData.objectPropertiesProvider) {
|
||||
this._objectPropertiesProvider = aData.objectPropertiesProvider;
|
||||
this._releaseObject = aData.releaseObject;
|
||||
this._propertiesToRows(aData.objectProperties, 0);
|
||||
this._rows = aData.objectProperties;
|
||||
}
|
||||
else if (aData.object) {
|
||||
this._localObjectActors = Object.create(null);
|
||||
this._rows = this._inspectObject(aData.object);
|
||||
}
|
||||
else {
|
||||
throw new Error("First argument must have a .remoteObject or " +
|
||||
"an .object property!");
|
||||
throw new Error("First argument must have an objectActor or an " +
|
||||
"object property!");
|
||||
}
|
||||
|
||||
if (this._treeBox) {
|
||||
|
@ -128,13 +135,22 @@ PropertyTreeView.prototype = {
|
|||
* @param number aLevel
|
||||
* The level you want to give to each property in the remote object.
|
||||
*/
|
||||
_updateRemoteObject: function PTV__updateRemoteObject(aObject, aLevel)
|
||||
_propertiesToRows: function PTV__propertiesToRows(aObject, aLevel)
|
||||
{
|
||||
aObject.forEach(function(aElement) {
|
||||
aElement.level = aLevel;
|
||||
aElement.isOpened = false;
|
||||
aElement.children = null;
|
||||
});
|
||||
aObject.forEach(function(aItem) {
|
||||
aItem._level = aLevel;
|
||||
aItem._open = false;
|
||||
aItem._children = null;
|
||||
|
||||
if (this._releaseObject) {
|
||||
["value", "get", "set"].forEach(function(aProp) {
|
||||
let val = aItem[aProp];
|
||||
if (val && val.actor) {
|
||||
this._objectActors.push(val.actor);
|
||||
}
|
||||
}, this);
|
||||
}
|
||||
}, this);
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -143,42 +159,53 @@ PropertyTreeView.prototype = {
|
|||
* @private
|
||||
* @param object aObject
|
||||
* The object you want to inspect.
|
||||
* @return array
|
||||
* The array of properties, each being described in a way that is
|
||||
* usable by the tree view.
|
||||
*/
|
||||
_inspectObject: function PTV__inspectObject(aObject)
|
||||
{
|
||||
this._objectCache = {};
|
||||
this._remoteObjectProvider = this._localObjectProvider.bind(this);
|
||||
let children = WebConsoleUtils.namesAndValuesOf(aObject, this._objectCache);
|
||||
this._updateRemoteObject(children, 0);
|
||||
this._objectPropertiesProvider = this._localPropertiesProvider.bind(this);
|
||||
let children =
|
||||
WebConsoleUtils.inspectObject(aObject, this._localObjectGrip.bind(this));
|
||||
this._propertiesToRows(children, 0);
|
||||
return children;
|
||||
},
|
||||
|
||||
/**
|
||||
* An object provider for when the user inspects local objects (not remote
|
||||
* Make a local fake object actor for the given object.
|
||||
*
|
||||
* @private
|
||||
* @param object aObject
|
||||
* The object to make an actor for.
|
||||
* @return object
|
||||
* The fake actor grip that represents the given object.
|
||||
*/
|
||||
_localObjectGrip: function PTV__localObjectGrip(aObject)
|
||||
{
|
||||
let grip = WebConsoleUtils.getObjectGrip(aObject);
|
||||
grip.actor = "obj" + gSequenceId();
|
||||
this._localObjectActors[grip.actor] = aObject;
|
||||
return grip;
|
||||
},
|
||||
|
||||
/**
|
||||
* A properties 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 string aActor
|
||||
* The ID of the object actor you want.
|
||||
* @param function aCallback
|
||||
* The function you want to receive the object.
|
||||
* The function you want to receive the list of properties.
|
||||
*/
|
||||
_localObjectProvider:
|
||||
function PTV__localObjectProvider(aFromCacheId, aObjectId, aDestCacheId,
|
||||
aCallback)
|
||||
_localPropertiesProvider:
|
||||
function PTV__localPropertiesProvider(aActor, aCallback)
|
||||
{
|
||||
let object = WebConsoleUtils.namesAndValuesOf(this._objectCache[aObjectId],
|
||||
this._objectCache);
|
||||
aCallback({cacheId: aFromCacheId,
|
||||
objectId: aObjectId,
|
||||
object: object,
|
||||
childrenCacheId: aDestCacheId || aFromCacheId,
|
||||
});
|
||||
let object = this._localObjectActors[aActor];
|
||||
let properties =
|
||||
WebConsoleUtils.inspectObject(object, this._localObjectGrip.bind(this));
|
||||
aCallback(properties);
|
||||
},
|
||||
|
||||
/** nsITreeView interface implementation **/
|
||||
|
@ -187,18 +214,20 @@ PropertyTreeView.prototype = {
|
|||
|
||||
get rowCount() { return this._rows.length; },
|
||||
setTree: function(treeBox) { this._treeBox = treeBox; },
|
||||
getCellText: function(idx, column) {
|
||||
getCellText: function PTV_getCellText(idx, column)
|
||||
{
|
||||
let row = this._rows[idx];
|
||||
return row.name + ": " + row.value;
|
||||
return row.name + ": " + WebConsoleUtils.getPropertyPanelValue(row);
|
||||
},
|
||||
getLevel: function(idx) {
|
||||
return this._rows[idx].level;
|
||||
return this._rows[idx]._level;
|
||||
},
|
||||
isContainer: function(idx) {
|
||||
return !!this._rows[idx].inspectable;
|
||||
return typeof this._rows[idx].value == "object" && this._rows[idx].value &&
|
||||
this._rows[idx].value.inspectable;
|
||||
},
|
||||
isContainerOpen: function(idx) {
|
||||
return this._rows[idx].isOpened;
|
||||
return this._rows[idx]._open;
|
||||
},
|
||||
isContainerEmpty: function(idx) { return false; },
|
||||
isSeparator: function(idx) { return false; },
|
||||
|
@ -221,22 +250,22 @@ PropertyTreeView.prototype = {
|
|||
|
||||
hasNextSibling: function(idx, after)
|
||||
{
|
||||
var thisLevel = this.getLevel(idx);
|
||||
return this._rows.slice(after + 1).some(function (r) r.level == thisLevel);
|
||||
let 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) {
|
||||
if (!this.isContainer(idx)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (item.isOpened) {
|
||||
if (item._open) {
|
||||
this._treeBox.beginUpdateBatch();
|
||||
item.isOpened = false;
|
||||
item._open = false;
|
||||
|
||||
var thisLevel = item.level;
|
||||
var thisLevel = item._level;
|
||||
var t = idx + 1, deleteCount = 0;
|
||||
while (t < this._rows.length && this.getLevel(t++) > thisLevel) {
|
||||
deleteCount++;
|
||||
|
@ -251,31 +280,27 @@ PropertyTreeView.prototype = {
|
|||
}
|
||||
else {
|
||||
let levelUpdate = true;
|
||||
let callback = function _onRemoteResponse(aResponse) {
|
||||
let callback = function _onRemoteResponse(aProperties) {
|
||||
this._treeBox.beginUpdateBatch();
|
||||
item.isOpened = true;
|
||||
|
||||
if (levelUpdate) {
|
||||
this._updateRemoteObject(aResponse.object, item.level + 1);
|
||||
item.children = aResponse.object;
|
||||
this._propertiesToRows(aProperties, item._level + 1);
|
||||
item._children = aProperties;
|
||||
}
|
||||
|
||||
this._rows.splice.apply(this._rows, [idx + 1, 0].concat(item.children));
|
||||
this._rows.splice.apply(this._rows, [idx + 1, 0].concat(item._children));
|
||||
|
||||
this._treeBox.rowCountChanged(idx + 1, item.children.length);
|
||||
this._treeBox.rowCountChanged(idx + 1, item._children.length);
|
||||
this._treeBox.invalidateRow(idx);
|
||||
this._treeBox.endUpdateBatch();
|
||||
item._open = true;
|
||||
}.bind(this);
|
||||
|
||||
if (!item.children) {
|
||||
let fromCacheId = item.level > 0 ? this._panelCacheId :
|
||||
this._rootCacheId;
|
||||
this._remoteObjectProvider(fromCacheId, item.objectId,
|
||||
this._panelCacheId, callback);
|
||||
if (!item._children) {
|
||||
this._objectPropertiesProvider(item.value.actor, callback);
|
||||
}
|
||||
else {
|
||||
levelUpdate = false;
|
||||
callback({object: item.children});
|
||||
callback(item._children);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -298,18 +323,23 @@ PropertyTreeView.prototype = {
|
|||
drop: function(index, orientation, dataTransfer) { },
|
||||
canDrop: function(index, orientation, dataTransfer) { return false; },
|
||||
|
||||
_cleanup: function PTV__cleanup()
|
||||
/**
|
||||
* Cleanup the property tree view.
|
||||
*/
|
||||
cleanup: function PTV_cleanup()
|
||||
{
|
||||
if (this._rows.length) {
|
||||
// Reset the existing _rows children to the initial state.
|
||||
this._updateRemoteObject(this._rows, 0);
|
||||
this._rows = [];
|
||||
if (this._releaseObject) {
|
||||
this._objectActors.forEach(this._releaseObject);
|
||||
delete this._objectPropertiesProvider;
|
||||
delete this._releaseObject;
|
||||
}
|
||||
if (this._localObjectActors) {
|
||||
delete this._localObjectActors;
|
||||
delete this._objectPropertiesProvider;
|
||||
}
|
||||
|
||||
delete this._objectCache;
|
||||
delete this._rootCacheId;
|
||||
delete this._panelCacheId;
|
||||
delete this._remoteObjectProvider;
|
||||
this._rows = [];
|
||||
this._objectActors = [];
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -459,3 +489,9 @@ PropertyPanel.prototype.destroy = function PP_destroy()
|
|||
this.tree = null;
|
||||
}
|
||||
|
||||
|
||||
function gSequenceId()
|
||||
{
|
||||
return gSequenceId.n++;
|
||||
}
|
||||
gSequenceId.n = 0;
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -8,7 +8,7 @@ function test()
|
|||
{
|
||||
waitForExplicitFinish();
|
||||
|
||||
addTab("data:text/html,test for bug 676722 - inspectable objects for window.console");
|
||||
addTab("data:text/html;charset=utf8,test for bug 676722 - inspectable objects for window.console");
|
||||
|
||||
gBrowser.selectedBrowser.addEventListener("load", function onLoad() {
|
||||
gBrowser.selectedBrowser.removeEventListener("load", onLoad, true);
|
||||
|
|
|
@ -21,7 +21,7 @@ function test() {
|
|||
browser.removeEventListener("DOMContentLoaded", testTimestamp, false);
|
||||
const TEST_TIMESTAMP = 12345678;
|
||||
let date = new Date(TEST_TIMESTAMP);
|
||||
let localizedString = WebConsoleUtils.l10n.timestampString(TEST_TIMESTAMP);
|
||||
let localizedString = WCU_l10n.timestampString(TEST_TIMESTAMP);
|
||||
isnot(localizedString.indexOf(date.getHours()), -1, "the localized " +
|
||||
"timestamp contains the hours");
|
||||
isnot(localizedString.indexOf(date.getMinutes()), -1, "the localized " +
|
||||
|
|
|
@ -81,7 +81,7 @@ function testContextMenuCopy() {
|
|||
}
|
||||
|
||||
function getExpectedClipboardText(aItem) {
|
||||
return "[" + WebConsoleUtils.l10n.timestampString(aItem.timestamp) + "] " +
|
||||
return "[" + WCU_l10n.timestampString(aItem.timestamp) + "] " +
|
||||
aItem.clipboardText;
|
||||
}
|
||||
|
||||
|
|
|
@ -37,14 +37,14 @@ function test() {
|
|||
|
||||
let uri = Services.io.newFileURI(dir);
|
||||
|
||||
addTab(uri.spec);
|
||||
addTab("data:text/html;charset=utf8,<p>test file URI");
|
||||
browser.addEventListener("load", function tabLoad() {
|
||||
browser.removeEventListener("load", tabLoad, true);
|
||||
openConsole(null, function(aHud) {
|
||||
hud = aHud;
|
||||
hud.jsterm.clearOutput();
|
||||
browser.addEventListener("load", tabReload, true);
|
||||
content.location.reload();
|
||||
content.location = uri.spec;
|
||||
});
|
||||
}, true);
|
||||
}
|
||||
|
|
|
@ -14,25 +14,35 @@ let tab1, tab2, win1, win2;
|
|||
let noErrors = true;
|
||||
|
||||
function tab1Loaded(aEvent) {
|
||||
browser.removeEventListener(aEvent.type, arguments.callee, true);
|
||||
browser.removeEventListener(aEvent.type, tab1Loaded, true);
|
||||
|
||||
win2 = OpenBrowserWindow();
|
||||
win2.addEventListener("load", win2Loaded, true);
|
||||
}
|
||||
|
||||
function win2Loaded(aEvent) {
|
||||
win2.removeEventListener(aEvent.type, arguments.callee, true);
|
||||
win2.removeEventListener(aEvent.type, win2Loaded, true);
|
||||
|
||||
tab2 = win2.gBrowser.addTab();
|
||||
tab2 = win2.gBrowser.addTab(TEST_URI);
|
||||
win2.gBrowser.selectedTab = tab2;
|
||||
tab2.linkedBrowser.addEventListener("load", tab2Loaded, true);
|
||||
tab2.linkedBrowser.contentWindow.location = TEST_URI;
|
||||
}
|
||||
|
||||
function tab2Loaded(aEvent) {
|
||||
tab2.linkedBrowser.removeEventListener(aEvent.type, arguments.callee, true);
|
||||
tab2.linkedBrowser.removeEventListener(aEvent.type, tab2Loaded, true);
|
||||
|
||||
waitForFocus(function() {
|
||||
let consolesOpened = 0;
|
||||
function onWebConsoleOpen() {
|
||||
consolesOpened++;
|
||||
if (consolesOpened == 2) {
|
||||
Services.obs.removeObserver(onWebConsoleOpen, "web-console-created");
|
||||
executeSoon(closeConsoles);
|
||||
}
|
||||
}
|
||||
|
||||
Services.obs.addObserver(onWebConsoleOpen, "web-console-created", false);
|
||||
|
||||
function openConsoles() {
|
||||
try {
|
||||
HUDService.activateHUDForContext(tab1);
|
||||
}
|
||||
|
@ -48,6 +58,20 @@ function tab2Loaded(aEvent) {
|
|||
ok(false, "HUDService.activateHUDForContext(tab2) exception: " + ex);
|
||||
noErrors = false;
|
||||
}
|
||||
}
|
||||
|
||||
let consolesClosed = 0;
|
||||
function onWebConsoleClose()
|
||||
{
|
||||
consolesClosed++;
|
||||
if (consolesClosed == 2) {
|
||||
Services.obs.removeObserver(onWebConsoleClose, "web-console-destroyed");
|
||||
executeSoon(testEnd);
|
||||
}
|
||||
}
|
||||
|
||||
function closeConsoles() {
|
||||
Services.obs.addObserver(onWebConsoleClose, "web-console-destroyed", false);
|
||||
|
||||
try {
|
||||
HUDService.deactivateHUDForContext(tab1);
|
||||
|
@ -64,20 +88,26 @@ function tab2Loaded(aEvent) {
|
|||
ok(false, "HUDService.deactivateHUDForContext(tab2) exception: " + ex);
|
||||
noErrors = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (noErrors) {
|
||||
ok(true, "there were no errors");
|
||||
}
|
||||
function testEnd() {
|
||||
ok(noErrors, "there were no errors");
|
||||
|
||||
win2.gBrowser.removeTab(tab2);
|
||||
Array.forEach(win1.gBrowser.tabs, function(aTab) {
|
||||
win1.gBrowser.removeTab(aTab);
|
||||
});
|
||||
Array.forEach(win2.gBrowser.tabs, function(aTab) {
|
||||
win2.gBrowser.removeTab(aTab);
|
||||
});
|
||||
|
||||
executeSoon(function() {
|
||||
win2.close();
|
||||
tab1 = tab2 = win1 = win2 = null;
|
||||
finishTest();
|
||||
});
|
||||
}
|
||||
|
||||
}, tab2.linkedBrowser.contentWindow);
|
||||
waitForFocus(openConsoles, tab2.linkedBrowser.contentWindow);
|
||||
}
|
||||
|
||||
function test() {
|
||||
|
|
|
@ -10,10 +10,12 @@
|
|||
|
||||
const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/test-bug-599725-response-headers.sjs";
|
||||
|
||||
function performTest(lastFinishedRequest)
|
||||
function performTest(lastFinishedRequest, aConsole)
|
||||
{
|
||||
ok(lastFinishedRequest, "page load was logged");
|
||||
|
||||
let headers = null;
|
||||
|
||||
function readHeader(aName)
|
||||
{
|
||||
for (let header of headers) {
|
||||
|
@ -24,13 +26,16 @@ function performTest(lastFinishedRequest)
|
|||
return null;
|
||||
}
|
||||
|
||||
let headers = lastFinishedRequest.log.entries[0].response.headers;
|
||||
ok(headers, "we have the response headers");
|
||||
ok(!readHeader("Content-Type"), "we do not have the Content-Type header");
|
||||
isnot(readHeader("Content-Length"), 60, "Content-Length != 60");
|
||||
aConsole.webConsoleClient.getResponseHeaders(lastFinishedRequest.actor,
|
||||
function (aResponse) {
|
||||
headers = aResponse.headers;
|
||||
ok(headers, "we have the response headers");
|
||||
ok(!readHeader("Content-Type"), "we do not have the Content-Type header");
|
||||
isnot(readHeader("Content-Length"), 60, "Content-Length != 60");
|
||||
executeSoon(finishTest);
|
||||
});
|
||||
|
||||
HUDService.lastFinishedRequestCallback = null;
|
||||
executeSoon(finishTest);
|
||||
}
|
||||
|
||||
function test()
|
||||
|
|
|
@ -10,39 +10,49 @@
|
|||
|
||||
const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/test-bug-600183-charset.html";
|
||||
|
||||
function performTest(lastFinishedRequest)
|
||||
function performTest(lastFinishedRequest, aConsole)
|
||||
{
|
||||
ok(lastFinishedRequest, "charset test page was loaded and logged");
|
||||
|
||||
let body = lastFinishedRequest.log.entries[0].response.content.text;
|
||||
ok(body, "we have the response body");
|
||||
aConsole.webConsoleClient.getResponseContent(lastFinishedRequest.actor,
|
||||
function (aResponse) {
|
||||
ok(!aResponse.contentDiscarded, "response body was not discarded");
|
||||
|
||||
let chars = "\u7684\u95ee\u5019!"; // 的问候!
|
||||
isnot(body.indexOf("<p>" + chars + "</p>"), -1,
|
||||
"found the chinese simplified string");
|
||||
let body = aResponse.content.text;
|
||||
ok(body, "we have the response body");
|
||||
|
||||
let chars = "\u7684\u95ee\u5019!"; // 的问候!
|
||||
isnot(body.indexOf("<p>" + chars + "</p>"), -1,
|
||||
"found the chinese simplified string");
|
||||
executeSoon(finishTest);
|
||||
});
|
||||
|
||||
HUDService.lastFinishedRequestCallback = null;
|
||||
executeSoon(finishTest);
|
||||
}
|
||||
|
||||
function test()
|
||||
{
|
||||
addTab("data:text/html;charset=utf-8,Web Console - bug 600183 test");
|
||||
|
||||
let initialLoad = true;
|
||||
|
||||
browser.addEventListener("load", function onLoad() {
|
||||
if (initialLoad) {
|
||||
openConsole(null, function(hud) {
|
||||
browser.removeEventListener("load", onLoad, true);
|
||||
|
||||
hud.ui.saveRequestAndResponseBodies = true;
|
||||
HUDService.lastFinishedRequestCallback = performTest;
|
||||
openConsole(null, function(hud) {
|
||||
hud.ui.saveRequestAndResponseBodies = true;
|
||||
|
||||
content.location = TEST_URI;
|
||||
waitForSuccess({
|
||||
name: "saveRequestAndResponseBodies update",
|
||||
validatorFn: function()
|
||||
{
|
||||
return hud.ui.saveRequestAndResponseBodies;
|
||||
},
|
||||
successFn: function()
|
||||
{
|
||||
HUDService.lastFinishedRequestCallback = performTest;
|
||||
content.location = TEST_URI;
|
||||
},
|
||||
failureFn: finishTest,
|
||||
});
|
||||
initialLoad = false;
|
||||
} else {
|
||||
browser.removeEventListener("load", onLoad, true);
|
||||
}
|
||||
});
|
||||
}, true);
|
||||
}
|
||||
|
|
|
@ -16,14 +16,14 @@ const MINIMUM_CONSOLE_HEIGHT = 150;
|
|||
const MINIMUM_PAGE_HEIGHT = 50;
|
||||
const HEIGHT_PREF = "devtools.hud.height";
|
||||
|
||||
let hud, newHeight, height, innerHeight;
|
||||
let hud, newHeight, height, innerHeight, testDriver;
|
||||
|
||||
function performTests(aWebConsole)
|
||||
function testGen()
|
||||
{
|
||||
hud = aWebConsole.iframe;
|
||||
height = parseInt(hud.style.height);
|
||||
|
||||
toggleConsole();
|
||||
yield;
|
||||
|
||||
is(newHeight, height, "same height after reopening the console");
|
||||
is(Services.prefs.getIntPref(HEIGHT_PREF), HUDService.lastConsoleHeight,
|
||||
|
@ -31,6 +31,7 @@ function performTests(aWebConsole)
|
|||
|
||||
setHeight(Math.ceil(innerHeight * 0.5));
|
||||
toggleConsole();
|
||||
yield;
|
||||
|
||||
is(newHeight, height, "same height after reopening the console");
|
||||
is(Services.prefs.getIntPref(HEIGHT_PREF), HUDService.lastConsoleHeight,
|
||||
|
@ -38,6 +39,7 @@ function performTests(aWebConsole)
|
|||
|
||||
setHeight(MINIMUM_CONSOLE_HEIGHT - 1);
|
||||
toggleConsole();
|
||||
yield;
|
||||
|
||||
is(newHeight, MINIMUM_CONSOLE_HEIGHT, "minimum console height is respected");
|
||||
is(Services.prefs.getIntPref(HEIGHT_PREF), HUDService.lastConsoleHeight,
|
||||
|
@ -45,6 +47,7 @@ function performTests(aWebConsole)
|
|||
|
||||
setHeight(innerHeight - MINIMUM_PAGE_HEIGHT + 1);
|
||||
toggleConsole();
|
||||
yield;
|
||||
|
||||
is(newHeight, innerHeight - MINIMUM_PAGE_HEIGHT,
|
||||
"minimum page height is respected");
|
||||
|
@ -54,6 +57,7 @@ function performTests(aWebConsole)
|
|||
setHeight(Math.ceil(innerHeight * 0.6));
|
||||
Services.prefs.setIntPref(HEIGHT_PREF, -1);
|
||||
toggleConsole();
|
||||
yield;
|
||||
|
||||
is(newHeight, height, "same height after reopening the console");
|
||||
is(Services.prefs.getIntPref(HEIGHT_PREF), -1, "pref is not updated");
|
||||
|
@ -62,17 +66,23 @@ function performTests(aWebConsole)
|
|||
HUDService.lastConsoleHeight = 0;
|
||||
Services.prefs.setIntPref(HEIGHT_PREF, 0);
|
||||
|
||||
hud = testDriver = null;
|
||||
executeSoon(finishTest);
|
||||
|
||||
yield;
|
||||
}
|
||||
|
||||
function toggleConsole()
|
||||
{
|
||||
closeConsole();
|
||||
openConsole();
|
||||
closeConsole(null, function() {
|
||||
openConsole(null, function() {
|
||||
let hudId = HUDService.getHudIdByWindow(content);
|
||||
hud = HUDService.hudReferences[hudId].iframe;
|
||||
newHeight = parseInt(hud.style.height);
|
||||
|
||||
let hudId = HUDService.getHudIdByWindow(content);
|
||||
hud = HUDService.hudReferences[hudId].iframe;
|
||||
newHeight = parseInt(hud.style.height);
|
||||
testDriver.next();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function setHeight(aHeight)
|
||||
|
@ -87,7 +97,11 @@ function test()
|
|||
browser.addEventListener("load", function onLoad() {
|
||||
browser.removeEventListener("load", onLoad, true);
|
||||
innerHeight = content.innerHeight;
|
||||
openConsole(null, performTests);
|
||||
openConsole(null, function(aHud) {
|
||||
hud = aHud.iframe;
|
||||
testDriver = testGen();
|
||||
testDriver.next();
|
||||
});
|
||||
}, true);
|
||||
}
|
||||
|
||||
|
|
|
@ -86,8 +86,17 @@ function onpopupshown2(aEvent)
|
|||
});
|
||||
}, false);
|
||||
|
||||
executeSoon(function() {
|
||||
menupopups[1].hidePopup();
|
||||
waitForSuccess({
|
||||
name: "saveRequestAndResponseBodies update",
|
||||
validatorFn: function()
|
||||
{
|
||||
return huds[1].ui.saveRequestAndResponseBodies;
|
||||
},
|
||||
successFn: function()
|
||||
{
|
||||
menupopups[1].hidePopup();
|
||||
},
|
||||
failureFn: finishTest,
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -147,8 +156,17 @@ function onpopupshown1(aEvent)
|
|||
}, tabs[runCount*2 + 1].linkedBrowser.contentWindow);
|
||||
}, false);
|
||||
|
||||
executeSoon(function() {
|
||||
menupopups[0].hidePopup();
|
||||
waitForSuccess({
|
||||
name: "saveRequestAndResponseBodies update",
|
||||
validatorFn: function()
|
||||
{
|
||||
return huds[0].ui.saveRequestAndResponseBodies;
|
||||
},
|
||||
successFn: function()
|
||||
{
|
||||
menupopups[0].hidePopup();
|
||||
},
|
||||
failureFn: finishTest,
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -80,6 +80,6 @@ function performTest(HUD) {
|
|||
}
|
||||
|
||||
function getExpectedClipboardText(aItem) {
|
||||
return "[" + WebConsoleUtils.l10n.timestampString(aItem.timestamp) + "] " +
|
||||
return "[" + WCU_l10n.timestampString(aItem.timestamp) + "] " +
|
||||
aItem.clipboardText;
|
||||
}
|
||||
|
|
|
@ -58,7 +58,7 @@ function getExpectedClipboardText(aItemCount) {
|
|||
for (let i = 0; i < aItemCount; i++) {
|
||||
let item = outputNode.getItemAtIndex(i);
|
||||
expectedClipboardText.push("[" +
|
||||
WebConsoleUtils.l10n.timestampString(item.timestamp) + "] " +
|
||||
WCU_l10n.timestampString(item.timestamp) + "] " +
|
||||
item.clipboardText);
|
||||
}
|
||||
return expectedClipboardText.join("\n");
|
||||
|
|
|
@ -10,20 +10,86 @@
|
|||
const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/test-bug-630733-response-redirect-headers.sjs";
|
||||
|
||||
let lastFinishedRequests = {};
|
||||
let webConsoleClient;
|
||||
|
||||
function requestDoneCallback(aHttpRequest)
|
||||
function requestDoneCallback(aHttpRequest )
|
||||
{
|
||||
let status = aHttpRequest.log.entries[0].response.status;
|
||||
let status = aHttpRequest.response.status;
|
||||
lastFinishedRequests[status] = aHttpRequest;
|
||||
}
|
||||
|
||||
function performTest(aEvent)
|
||||
function consoleOpened(hud)
|
||||
{
|
||||
webConsoleClient = hud.ui.webConsoleClient;
|
||||
hud.ui.saveRequestAndResponseBodies = true;
|
||||
|
||||
waitForSuccess({
|
||||
name: "saveRequestAndResponseBodies update",
|
||||
validatorFn: function()
|
||||
{
|
||||
return hud.ui.saveRequestAndResponseBodies;
|
||||
},
|
||||
successFn: function()
|
||||
{
|
||||
HUDService.lastFinishedRequestCallback = requestDoneCallback;
|
||||
waitForSuccess(waitForResponses);
|
||||
content.location = TEST_URI;
|
||||
},
|
||||
failureFn: finishTest,
|
||||
});
|
||||
|
||||
let waitForResponses = {
|
||||
name: "301 and 404 responses",
|
||||
validatorFn: function()
|
||||
{
|
||||
return "301" in lastFinishedRequests &&
|
||||
"404" in lastFinishedRequests;
|
||||
},
|
||||
successFn: getHeaders,
|
||||
failureFn: finishTest,
|
||||
};
|
||||
}
|
||||
|
||||
function getHeaders()
|
||||
{
|
||||
HUDService.lastFinishedRequestCallback = null;
|
||||
|
||||
ok("301" in lastFinishedRequests, "request 1: 301 Moved Permanently");
|
||||
ok("404" in lastFinishedRequests, "request 2: 404 Not found");
|
||||
|
||||
webConsoleClient.getResponseHeaders(lastFinishedRequests["301"].actor,
|
||||
function (aResponse) {
|
||||
lastFinishedRequests["301"].response.headers = aResponse.headers;
|
||||
|
||||
webConsoleClient.getResponseHeaders(lastFinishedRequests["404"].actor,
|
||||
function (aResponse) {
|
||||
lastFinishedRequests["404"].response.headers = aResponse.headers;
|
||||
executeSoon(getContent);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function getContent()
|
||||
{
|
||||
webConsoleClient.getResponseContent(lastFinishedRequests["301"].actor,
|
||||
function (aResponse) {
|
||||
lastFinishedRequests["301"].response.content = aResponse.content;
|
||||
lastFinishedRequests["301"].discardResponseBody = aResponse.contentDiscarded;
|
||||
|
||||
webConsoleClient.getResponseContent(lastFinishedRequests["404"].actor,
|
||||
function (aResponse) {
|
||||
lastFinishedRequests["404"].response.content = aResponse.content;
|
||||
lastFinishedRequests["404"].discardResponseBody =
|
||||
aResponse.contentDiscarded;
|
||||
|
||||
webConsoleClient = null;
|
||||
executeSoon(performTest);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function performTest()
|
||||
{
|
||||
function readHeader(aName)
|
||||
{
|
||||
for (let header of headers) {
|
||||
|
@ -34,7 +100,7 @@ function performTest(aEvent)
|
|||
return null;
|
||||
}
|
||||
|
||||
let headers = lastFinishedRequests["301"].log.entries[0].response.headers;
|
||||
let headers = lastFinishedRequests["301"].response.headers;
|
||||
is(readHeader("Content-Type"), "text/html",
|
||||
"we do have the Content-Type header");
|
||||
is(readHeader("Content-Length"), 71, "Content-Length is correct");
|
||||
|
@ -42,14 +108,17 @@ function performTest(aEvent)
|
|||
"Content-Length is correct");
|
||||
is(readHeader("x-foobar-bug630733"), "bazbaz",
|
||||
"X-Foobar-bug630733 is correct");
|
||||
let body = lastFinishedRequests["301"].log.entries[0].response.content;
|
||||
ok(!body.text, "body discarded for request 1");
|
||||
|
||||
headers = lastFinishedRequests["404"].log.entries[0].response.headers;
|
||||
let body = lastFinishedRequests["301"].response.content;
|
||||
ok(!body.text, "body discarded for request 1");
|
||||
ok(lastFinishedRequests["301"].discardResponseBody,
|
||||
"body discarded for request 1 (confirmed)");
|
||||
|
||||
headers = lastFinishedRequests["404"].response.headers;
|
||||
ok(!readHeader("Location"), "no Location header");
|
||||
ok(!readHeader("x-foobar-bug630733"), "no X-Foobar-bug630733 header");
|
||||
|
||||
body = lastFinishedRequests["404"].log.entries[0].response.content.text;
|
||||
body = lastFinishedRequests["404"].response.content.text;
|
||||
isnot(body.indexOf("404"), -1,
|
||||
"body is correct for request 2");
|
||||
|
||||
|
@ -61,19 +130,8 @@ function test()
|
|||
{
|
||||
addTab("data:text/html;charset=utf-8,<p>Web Console test for bug 630733");
|
||||
|
||||
browser.addEventListener("load", function onLoad1(aEvent) {
|
||||
browser.removeEventListener(aEvent.type, onLoad1, true);
|
||||
|
||||
openConsole(null, function(hud) {
|
||||
hud.ui.saveRequestAndResponseBodies = true;
|
||||
HUDService.lastFinishedRequestCallback = requestDoneCallback;
|
||||
|
||||
browser.addEventListener("load", function onLoad2(aEvent) {
|
||||
browser.removeEventListener(aEvent.type, onLoad2, true);
|
||||
executeSoon(performTest);
|
||||
}, true);
|
||||
|
||||
content.location = TEST_URI;
|
||||
});
|
||||
browser.addEventListener("load", function onLoad(aEvent) {
|
||||
browser.removeEventListener(aEvent.type, onLoad, true);
|
||||
openConsole(null, consoleOpened);
|
||||
}, true);
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@ function test() {
|
|||
|
||||
function consoleOpened(HUD) {
|
||||
let tmp = {};
|
||||
Cu.import("resource:///modules/WebConsoleUtils.jsm", tmp);
|
||||
Cu.import("resource://gre/modules/devtools/WebConsoleUtils.jsm", tmp);
|
||||
let WCU = tmp.WebConsoleUtils;
|
||||
let JSPropertyProvider = tmp.JSPropertyProvider;
|
||||
tmp = null;
|
||||
|
@ -117,7 +117,7 @@ function testPropertyPanel(aPanel) {
|
|||
ok(find("iter1: Iterator", false),
|
||||
"iter1 is correctly displayed in the Property Panel");
|
||||
|
||||
ok(find("iter2: Iterator", false),
|
||||
ok(find("iter2: Object", false),
|
||||
"iter2 is correctly displayed in the Property Panel");
|
||||
|
||||
executeSoon(finishTest);
|
||||
|
|
|
@ -25,7 +25,7 @@ function test()
|
|||
hud = aHud;
|
||||
|
||||
HUDService.lastFinishedRequestCallback = function(aRequest) {
|
||||
lastRequest = aRequest.log.entries[0];
|
||||
lastRequest = aRequest;
|
||||
if (requestCallback) {
|
||||
requestCallback();
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@ function consoleOpened(aHud) {
|
|||
let completeNode = jsterm.completeNode;
|
||||
|
||||
let tmp = {};
|
||||
Cu.import("resource:///modules/WebConsoleUtils.jsm", tmp);
|
||||
Cu.import("resource://gre/modules/devtools/WebConsoleUtils.jsm", tmp);
|
||||
let WCU = tmp.WebConsoleUtils;
|
||||
tmp = null;
|
||||
|
||||
|
@ -38,7 +38,8 @@ function consoleOpened(aHud) {
|
|||
// __defineGetter__ __defineSetter__ __lookupGetter__ __lookupSetter__
|
||||
// constructor hasOwnProperty isPrototypeOf propertyIsEnumerable
|
||||
// toLocaleString toSource toString unwatch valueOf watch.
|
||||
let props = WCU.namesAndValuesOf(content.wrappedJSObject.document.body);
|
||||
let props = WCU.inspectObject(content.wrappedJSObject.document.body,
|
||||
function() { });
|
||||
is(popup.itemCount, 14 + props.length, "popup.itemCount is correct");
|
||||
|
||||
popup._panel.addEventListener("popuphidden", autocompletePopupHidden, false);
|
||||
|
|
|
@ -41,7 +41,7 @@ function testConsoleDir(outputNode) {
|
|||
if (text == "querySelectorAll: function querySelectorAll()") {
|
||||
foundQSA = true;
|
||||
}
|
||||
else if (text == "location: Object") {
|
||||
else if (text == "location: Location") {
|
||||
foundLocation = true;
|
||||
}
|
||||
else if (text == "write: function write()") {
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
const TEST_HTTPS_URI = "https://example.com/browser/browser/devtools/webconsole/test/test-bug-737873-mixedcontent.html";
|
||||
|
||||
function test() {
|
||||
addTab("data:text/html,Web Console basic network logging test");
|
||||
addTab("data:text/html;charset=utf8,Web Console mixed content test");
|
||||
browser.addEventListener("load", onLoad, true);
|
||||
}
|
||||
|
||||
|
@ -68,8 +68,9 @@ function testClickOpenNewTab(warningNode) {
|
|||
let oldOpenUILinkIn = window.openUILinkIn;
|
||||
|
||||
window.openUILinkIn = function(aLink) {
|
||||
if (aLink == "https://developer.mozilla.org/en/Security/MixedContent");
|
||||
linkOpened = true;
|
||||
if (aLink == "https://developer.mozilla.org/en/Security/MixedContent") {
|
||||
linkOpened = true;
|
||||
}
|
||||
}
|
||||
|
||||
EventUtils.synthesizeMouse(warningNode, 2, 2, {},
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
// Tests that code completion works properly.
|
||||
|
||||
function test() {
|
||||
addTab("about:addons");
|
||||
addTab("about:credits");
|
||||
browser.addEventListener("load", function onLoad() {
|
||||
browser.removeEventListener("load", onLoad, true);
|
||||
openConsole(null, testChrome);
|
||||
|
@ -15,7 +15,7 @@ function test() {
|
|||
|
||||
function testChrome(hud) {
|
||||
ok(hud, "we have a console");
|
||||
|
||||
|
||||
ok(hud.iframe, "we have the console iframe");
|
||||
|
||||
let jsterm = hud.jsterm;
|
||||
|
|
|
@ -52,7 +52,7 @@ function testClipboard() {
|
|||
for (let i = 0; i < outputNode.itemCount; i++) {
|
||||
let item = outputNode.getItemAtIndex(i);
|
||||
clipboardTexts.push("[" +
|
||||
WebConsoleUtils.l10n.timestampString(item.timestamp) +
|
||||
WCU_l10n.timestampString(item.timestamp) +
|
||||
"] " + item.clipboardText);
|
||||
}
|
||||
|
||||
|
|
|
@ -111,10 +111,10 @@ function testJSTerm(hud)
|
|||
|
||||
let foundTab = null;
|
||||
waitForSuccess({
|
||||
name: "help tab opened",
|
||||
name: "help tabs opened",
|
||||
validatorFn: function()
|
||||
{
|
||||
let newTabOpen = gBrowser.tabs.length == tabs + 1;
|
||||
let newTabOpen = gBrowser.tabs.length == tabs + 3;
|
||||
if (!newTabOpen) {
|
||||
return false;
|
||||
}
|
||||
|
@ -124,7 +124,9 @@ function testJSTerm(hud)
|
|||
},
|
||||
successFn: function()
|
||||
{
|
||||
gBrowser.removeTab(foundTab);
|
||||
gBrowser.removeTab(gBrowser.tabs[gBrowser.tabs.length - 1]);
|
||||
gBrowser.removeTab(gBrowser.tabs[gBrowser.tabs.length - 1]);
|
||||
gBrowser.removeTab(gBrowser.tabs[gBrowser.tabs.length - 1]);
|
||||
nextTest();
|
||||
},
|
||||
failureFn: nextTest,
|
||||
|
@ -176,7 +178,7 @@ function testJSTerm(hud)
|
|||
jsterm.clearOutput();
|
||||
jsterm.execute("pprint(print)");
|
||||
checkResult(function(nodes) {
|
||||
return nodes[0].textContent.indexOf("aJSTerm.") > -1;
|
||||
return nodes[0].textContent.indexOf("aOwner.helperResult") > -1;
|
||||
}, "pprint(function) shows source", 1);
|
||||
yield;
|
||||
|
||||
|
|
|
@ -21,7 +21,6 @@ const TEST_DATA_JSON_CONTENT =
|
|||
|
||||
let lastRequest = null;
|
||||
let requestCallback = null;
|
||||
let lastActivity = null;
|
||||
|
||||
function test()
|
||||
{
|
||||
|
@ -33,19 +32,34 @@ function test()
|
|||
openConsole(null, function(aHud) {
|
||||
hud = aHud;
|
||||
|
||||
HUDService.lastFinishedRequestCallback = function(aRequest) {
|
||||
lastRequest = aRequest.log.entries[0];
|
||||
lastActivity = aRequest;
|
||||
if (requestCallback) {
|
||||
requestCallback();
|
||||
}
|
||||
};
|
||||
HUDService.lastFinishedRequestCallback = requestCallbackWrapper;
|
||||
|
||||
executeSoon(testPageLoad);
|
||||
});
|
||||
}, true);
|
||||
}
|
||||
|
||||
function requestCallbackWrapper(aRequest)
|
||||
{
|
||||
lastRequest = aRequest;
|
||||
|
||||
hud.ui.webConsoleClient.getResponseContent(lastRequest.actor,
|
||||
function(aResponse) {
|
||||
lastRequest.response.content = aResponse.content;
|
||||
lastRequest.discardResponseBody = aResponse.contentDiscarded;
|
||||
|
||||
hud.ui.webConsoleClient.getRequestPostData(lastRequest.actor,
|
||||
function(aResponse) {
|
||||
lastRequest.request.postData = aResponse.postData;
|
||||
lastRequest.discardRequestBody = aResponse.postDataDiscarded;
|
||||
|
||||
if (requestCallback) {
|
||||
requestCallback();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function testPageLoad()
|
||||
{
|
||||
requestCallback = function() {
|
||||
|
@ -55,8 +69,10 @@ function testPageLoad()
|
|||
is(lastRequest.request.url, TEST_NETWORK_REQUEST_URI,
|
||||
"Logged network entry is page load");
|
||||
is(lastRequest.request.method, "GET", "Method is correct");
|
||||
ok(!lastRequest.request.postData, "No request body was stored");
|
||||
ok(!lastRequest.request.postData.text, "No request body was stored");
|
||||
ok(lastRequest.discardRequestBody, "Request body was discarded");
|
||||
ok(!lastRequest.response.content.text, "No response body was stored");
|
||||
ok(lastRequest.discardResponseBody, "Response body was discarded");
|
||||
|
||||
lastRequest = null;
|
||||
requestCallback = null;
|
||||
|
@ -67,14 +83,29 @@ function testPageLoad()
|
|||
}
|
||||
|
||||
function testPageLoadBody()
|
||||
{
|
||||
// Turn on logging of request bodies and check again.
|
||||
hud.ui.saveRequestAndResponseBodies = true;
|
||||
|
||||
waitForSuccess({
|
||||
name: "saveRequestAndResponseBodies update",
|
||||
validatorFn: function()
|
||||
{
|
||||
return hud.ui.saveRequestAndResponseBodies;
|
||||
},
|
||||
successFn: testPageLoadBodyAfterSettingUpdate,
|
||||
failureFn: finishTest,
|
||||
});
|
||||
}
|
||||
|
||||
function testPageLoadBodyAfterSettingUpdate()
|
||||
{
|
||||
let loaded = false;
|
||||
let requestCallbackInvoked = false;
|
||||
|
||||
// Turn on logging of request bodies and check again.
|
||||
hud.ui.saveRequestAndResponseBodies = true;
|
||||
requestCallback = function() {
|
||||
ok(lastRequest, "Page load was logged again");
|
||||
ok(!lastRequest.discardResponseBody, "Response body was not discarded");
|
||||
is(lastRequest.response.content.text.indexOf("<!DOCTYPE HTML>"), 0,
|
||||
"Response body's beginning is okay");
|
||||
|
||||
|
@ -104,7 +135,8 @@ function testXhrGet()
|
|||
requestCallback = function() {
|
||||
ok(lastRequest, "testXhrGet() was logged");
|
||||
is(lastRequest.request.method, "GET", "Method is correct");
|
||||
ok(!lastRequest.request.postData, "No request body was sent");
|
||||
ok(!lastRequest.request.postData.text, "No request body was sent");
|
||||
ok(!lastRequest.discardRequestBody, "Request body was not discarded");
|
||||
is(lastRequest.response.content.text, TEST_DATA_JSON_CONTENT,
|
||||
"Response is correct");
|
||||
|
||||
|
@ -165,19 +197,18 @@ function testNetworkPanel()
|
|||
{
|
||||
// Open the NetworkPanel. The functionality of the NetworkPanel is tested
|
||||
// within separate test files.
|
||||
let networkPanel = hud.ui.openNetworkPanel(hud.ui.filterBox, lastActivity);
|
||||
is(networkPanel, hud.ui.filterBox._netPanel,
|
||||
"Network panel stored on anchor node");
|
||||
let networkPanel = hud.ui.openNetworkPanel(hud.ui.filterBox, lastRequest);
|
||||
|
||||
networkPanel.panel.addEventListener("load", function onLoad(aEvent) {
|
||||
networkPanel.panel.removeEventListener(aEvent.type, onLoad, true);
|
||||
networkPanel.panel.addEventListener("popupshown", function onPopupShown() {
|
||||
networkPanel.panel.removeEventListener("popupshown", onPopupShown, true);
|
||||
|
||||
is(hud.ui.filterBox._netPanel, networkPanel,
|
||||
"Network panel stored on anchor node");
|
||||
ok(true, "NetworkPanel was opened");
|
||||
|
||||
// All tests are done. Shutdown.
|
||||
networkPanel.panel.hidePopup();
|
||||
lastRequest = null;
|
||||
lastActivity = null;
|
||||
HUDService.lastFinishedRequestCallback = null;
|
||||
executeSoon(finishTest);
|
||||
}, true);
|
||||
|
|
|
@ -64,48 +64,37 @@ function testGen() {
|
|||
let hud = HUDService.getHudByWindow(content);
|
||||
let filterBox = hud.ui.filterBox;
|
||||
|
||||
let tempScope = {};
|
||||
Cu.import("resource:///modules/WebConsoleUtils.jsm", tempScope);
|
||||
let l10n = tempScope.WebConsoleUtils.l10n;
|
||||
tempScope = null;
|
||||
|
||||
let httpActivity = {
|
||||
meta: {
|
||||
stages: [],
|
||||
discardRequestBody: true,
|
||||
discardResponseBody: true,
|
||||
updates: [],
|
||||
discardRequestBody: true,
|
||||
discardResponseBody: true,
|
||||
startedDateTime: (new Date()).toISOString(),
|
||||
request: {
|
||||
url: "http://www.testpage.com",
|
||||
method: "GET",
|
||||
cookies: [],
|
||||
headers: [
|
||||
{ name: "foo", value: "bar" },
|
||||
],
|
||||
},
|
||||
log: {
|
||||
entries: [{
|
||||
startedDateTime: (new Date()).toISOString(),
|
||||
request: {
|
||||
url: "http://www.testpage.com",
|
||||
method: "GET",
|
||||
cookies: [],
|
||||
headers: [
|
||||
{ name: "foo", value: "bar" },
|
||||
],
|
||||
},
|
||||
response: {
|
||||
headers: [],
|
||||
content: {},
|
||||
},
|
||||
timings: {},
|
||||
}],
|
||||
response: {
|
||||
headers: [],
|
||||
content: {},
|
||||
},
|
||||
timings: {},
|
||||
};
|
||||
|
||||
let entry = httpActivity.log.entries[0];
|
||||
|
||||
let networkPanel = hud.ui.openNetworkPanel(filterBox, httpActivity);
|
||||
|
||||
is(filterBox._netPanel, networkPanel,
|
||||
"Network panel stored on the anchor object");
|
||||
|
||||
networkPanel.panel.addEventListener("load", function onLoad() {
|
||||
networkPanel.panel.removeEventListener("load", onLoad, true);
|
||||
testDriver.next();
|
||||
}, true);
|
||||
networkPanel._onUpdate = function() {
|
||||
networkPanel._onUpdate = null;
|
||||
executeSoon(function() {
|
||||
testDriver.next();
|
||||
});
|
||||
};
|
||||
|
||||
yield;
|
||||
|
||||
|
@ -128,8 +117,8 @@ function testGen() {
|
|||
|
||||
// Test request body.
|
||||
info("test 2: request body");
|
||||
httpActivity.meta.discardRequestBody = false;
|
||||
entry.request.postData = { text: "hello world" };
|
||||
httpActivity.discardRequestBody = false;
|
||||
httpActivity.request.postData = { text: "hello world" };
|
||||
networkPanel.update();
|
||||
|
||||
checkIsVisible(networkPanel, {
|
||||
|
@ -146,12 +135,12 @@ function testGen() {
|
|||
|
||||
// Test response header.
|
||||
info("test 3: response header");
|
||||
entry.timings.wait = 10;
|
||||
entry.response.httpVersion = "HTTP/3.14";
|
||||
entry.response.status = 999;
|
||||
entry.response.statusText = "earthquake win";
|
||||
entry.response.content.mimeType = "text/html";
|
||||
entry.response.headers.push(
|
||||
httpActivity.timings.wait = 10;
|
||||
httpActivity.response.httpVersion = "HTTP/3.14";
|
||||
httpActivity.response.status = 999;
|
||||
httpActivity.response.statusText = "earthquake win";
|
||||
httpActivity.response.content.mimeType = "text/html";
|
||||
httpActivity.response.headers.push(
|
||||
{ name: "Content-Type", value: "text/html" },
|
||||
{ name: "leaveHouses", value: "true" }
|
||||
);
|
||||
|
@ -175,8 +164,8 @@ function testGen() {
|
|||
|
||||
info("test 4");
|
||||
|
||||
httpActivity.meta.discardResponseBody = false;
|
||||
entry.timings.receive = 2;
|
||||
httpActivity.discardResponseBody = false;
|
||||
httpActivity.timings.receive = 2;
|
||||
networkPanel.update();
|
||||
|
||||
checkIsVisible(networkPanel, {
|
||||
|
@ -192,7 +181,7 @@ function testGen() {
|
|||
|
||||
info("test 5");
|
||||
|
||||
httpActivity.meta.stages.push("REQUEST_STOP", "TRANSACTION_CLOSE");
|
||||
httpActivity.updates.push("responseContent", "eventTimings");
|
||||
networkPanel.update();
|
||||
|
||||
checkNodeContent(networkPanel, "responseNoBodyInfo", "2ms");
|
||||
|
@ -210,20 +199,22 @@ function testGen() {
|
|||
|
||||
// Second run: Test for cookies and response body.
|
||||
info("test 6: cookies and response body");
|
||||
entry.request.cookies.push(
|
||||
httpActivity.request.cookies.push(
|
||||
{ name: "foo", value: "bar" },
|
||||
{ name: "hello", value: "world" }
|
||||
);
|
||||
entry.response.content.text = "get out here";
|
||||
httpActivity.response.content.text = "get out here";
|
||||
|
||||
networkPanel = hud.ui.openNetworkPanel(filterBox, httpActivity);
|
||||
is(filterBox._netPanel, networkPanel,
|
||||
"Network panel stored on httpActivity object");
|
||||
|
||||
networkPanel.panel.addEventListener("load", function onLoad() {
|
||||
networkPanel.panel.removeEventListener("load", onLoad, true);
|
||||
testDriver.next();
|
||||
}, true);
|
||||
networkPanel._onUpdate = function() {
|
||||
networkPanel._onUpdate = null;
|
||||
executeSoon(function() {
|
||||
testDriver.next();
|
||||
});
|
||||
};
|
||||
|
||||
yield;
|
||||
|
||||
|
@ -247,15 +238,17 @@ function testGen() {
|
|||
|
||||
// Check image request.
|
||||
info("test 7: image request");
|
||||
entry.response.headers[1].value = "image/png";
|
||||
entry.response.content.mimeType = "image/png";
|
||||
entry.request.url = TEST_IMG;
|
||||
httpActivity.response.headers[1].value = "image/png";
|
||||
httpActivity.response.content.mimeType = "image/png";
|
||||
httpActivity.request.url = TEST_IMG;
|
||||
|
||||
networkPanel = hud.ui.openNetworkPanel(filterBox, httpActivity);
|
||||
networkPanel.panel.addEventListener("load", function onLoad() {
|
||||
networkPanel.panel.removeEventListener("load", onLoad, true);
|
||||
testDriver.next();
|
||||
}, true);
|
||||
networkPanel._onUpdate = function() {
|
||||
networkPanel._onUpdate = null;
|
||||
executeSoon(function() {
|
||||
testDriver.next();
|
||||
});
|
||||
};
|
||||
|
||||
yield;
|
||||
|
||||
|
@ -296,15 +289,17 @@ function testGen() {
|
|||
|
||||
// Check cached image request.
|
||||
info("test 8: cached image request");
|
||||
entry.response.httpVersion = "HTTP/1.1";
|
||||
entry.response.status = 304;
|
||||
entry.response.statusText = "Not Modified";
|
||||
httpActivity.response.httpVersion = "HTTP/1.1";
|
||||
httpActivity.response.status = 304;
|
||||
httpActivity.response.statusText = "Not Modified";
|
||||
|
||||
networkPanel = hud.ui.openNetworkPanel(filterBox, httpActivity);
|
||||
networkPanel.panel.addEventListener("load", function onLoad() {
|
||||
networkPanel.panel.removeEventListener("load", onLoad, true);
|
||||
testDriver.next();
|
||||
}, true);
|
||||
networkPanel._onUpdate = function() {
|
||||
networkPanel._onUpdate = null;
|
||||
executeSoon(function() {
|
||||
testDriver.next();
|
||||
});
|
||||
};
|
||||
|
||||
yield;
|
||||
|
||||
|
@ -326,17 +321,19 @@ function testGen() {
|
|||
|
||||
// Test sent form data.
|
||||
info("test 9: sent form data");
|
||||
entry.request.postData.text = [
|
||||
httpActivity.request.postData.text = [
|
||||
"Content-Type: application/x-www-form-urlencoded",
|
||||
"Content-Length: 59",
|
||||
"name=rob&age=20"
|
||||
].join("\n");
|
||||
|
||||
networkPanel = hud.ui.openNetworkPanel(filterBox, httpActivity);
|
||||
networkPanel.panel.addEventListener("load", function onLoad() {
|
||||
networkPanel.panel.removeEventListener("load", onLoad, true);
|
||||
testDriver.next();
|
||||
}, true);
|
||||
networkPanel._onUpdate = function() {
|
||||
networkPanel._onUpdate = null;
|
||||
executeSoon(function() {
|
||||
testDriver.next();
|
||||
});
|
||||
};
|
||||
|
||||
yield;
|
||||
|
||||
|
@ -357,13 +354,15 @@ function testGen() {
|
|||
|
||||
// Test no space after Content-Type:
|
||||
info("test 10: no space after Content-Type header in post data");
|
||||
entry.request.postData.text = "Content-Type:application/x-www-form-urlencoded\n";
|
||||
httpActivity.request.postData.text = "Content-Type:application/x-www-form-urlencoded\n";
|
||||
|
||||
networkPanel = hud.ui.openNetworkPanel(filterBox, httpActivity);
|
||||
networkPanel.panel.addEventListener("load", function onLoad() {
|
||||
networkPanel.panel.removeEventListener("load", onLoad, true);
|
||||
testDriver.next();
|
||||
}, true);
|
||||
networkPanel._onUpdate = function() {
|
||||
networkPanel._onUpdate = null;
|
||||
executeSoon(function() {
|
||||
testDriver.next();
|
||||
});
|
||||
};
|
||||
|
||||
yield;
|
||||
|
||||
|
@ -384,16 +383,18 @@ function testGen() {
|
|||
|
||||
info("test 11: cached data");
|
||||
|
||||
entry.request.url = TEST_ENCODING_ISO_8859_1;
|
||||
entry.response.headers[1].value = "application/json";
|
||||
entry.response.content.mimeType = "application/json";
|
||||
entry.response.content.text = "my cached data is here!";
|
||||
httpActivity.request.url = TEST_ENCODING_ISO_8859_1;
|
||||
httpActivity.response.headers[1].value = "application/json";
|
||||
httpActivity.response.content.mimeType = "application/json";
|
||||
httpActivity.response.content.text = "my cached data is here!";
|
||||
|
||||
networkPanel = hud.ui.openNetworkPanel(filterBox, httpActivity);
|
||||
networkPanel.panel.addEventListener("load", function onLoad() {
|
||||
networkPanel.panel.removeEventListener("load", onLoad, true);
|
||||
testDriver.next();
|
||||
}, true);
|
||||
networkPanel._onUpdate = function() {
|
||||
networkPanel._onUpdate = null;
|
||||
executeSoon(function() {
|
||||
testDriver.next();
|
||||
});
|
||||
};
|
||||
|
||||
yield;
|
||||
|
||||
|
@ -417,14 +418,16 @@ function testGen() {
|
|||
// Test a response with a content type that can't be displayed in the
|
||||
// NetworkPanel.
|
||||
info("test 12: unknown content type");
|
||||
entry.response.headers[1].value = "application/x-shockwave-flash";
|
||||
entry.response.content.mimeType = "application/x-shockwave-flash";
|
||||
httpActivity.response.headers[1].value = "application/x-shockwave-flash";
|
||||
httpActivity.response.content.mimeType = "application/x-shockwave-flash";
|
||||
|
||||
networkPanel = hud.ui.openNetworkPanel(filterBox, httpActivity);
|
||||
networkPanel.panel.addEventListener("load", function onLoad() {
|
||||
networkPanel.panel.removeEventListener("load", onLoad, true);
|
||||
testDriver.next();
|
||||
}, true);
|
||||
networkPanel._onUpdate = function() {
|
||||
networkPanel._onUpdate = null;
|
||||
executeSoon(function() {
|
||||
testDriver.next();
|
||||
});
|
||||
};
|
||||
|
||||
yield;
|
||||
|
||||
|
@ -442,7 +445,7 @@ function testGen() {
|
|||
});
|
||||
|
||||
let responseString =
|
||||
l10n.getFormatStr("NetworkPanel.responseBodyUnableToDisplay.content",
|
||||
WCU_l10n.getFormatStr("NetworkPanel.responseBodyUnableToDisplay.content",
|
||||
["application/x-shockwave-flash"]);
|
||||
checkNodeContent(networkPanel, "responseBodyUnknownTypeContent", responseString);
|
||||
networkPanel.panel.hidePopup();
|
||||
|
|
|
@ -17,7 +17,7 @@ function testPropertyProvider() {
|
|||
browser.removeEventListener("load", testPropertyProvider, true);
|
||||
|
||||
let tmp = {};
|
||||
Cu.import("resource:///modules/WebConsoleUtils.jsm", tmp);
|
||||
Cu.import("resource://gre/modules/devtools/WebConsoleUtils.jsm", tmp);
|
||||
let JSPropertyProvider = tmp.JSPropertyProvider;
|
||||
tmp = null;
|
||||
|
||||
|
|
|
@ -6,8 +6,10 @@
|
|||
let tempScope = {};
|
||||
Cu.import("resource:///modules/HUDService.jsm", tempScope);
|
||||
let HUDService = tempScope.HUDService;
|
||||
Cu.import("resource:///modules/WebConsoleUtils.jsm", tempScope);
|
||||
Cu.import("resource://gre/modules/devtools/WebConsoleUtils.jsm", tempScope);
|
||||
let WebConsoleUtils = tempScope.WebConsoleUtils;
|
||||
const WEBCONSOLE_STRINGS_URI = "chrome://browser/locale/devtools/webconsole.properties";
|
||||
let WCU_l10n = new WebConsoleUtils.l10n(WEBCONSOLE_STRINGS_URI);
|
||||
|
||||
function log(aMsg)
|
||||
{
|
||||
|
@ -252,7 +254,7 @@ function tearDown()
|
|||
while (gBrowser.tabs.length > 1) {
|
||||
gBrowser.removeCurrentTab();
|
||||
}
|
||||
tab = browser = hudId = hud = filterBox = outputNode = cs = null;
|
||||
WCU_l10n = tab = browser = hudId = hud = filterBox = outputNode = cs = null;
|
||||
}
|
||||
|
||||
registerCleanupFunction(tearDown);
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html dir="ltr" xml:lang="en-US" lang="en-US"><head>
|
||||
<meta charset="utf8">
|
||||
<title>Mixed Content test - http on https</title>
|
||||
<script src="testscript.js"></script>
|
||||
<!--
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -817,11 +817,10 @@ jsbIndentCharDesc=The chars used to indent each line
|
|||
# does.
|
||||
jsbIndentCharManual=The chars used to indent each line. The possible choices are space or tab.
|
||||
|
||||
# LOCALIZATION NOTE (jsbPreserveNewlinesDesc) A very short description of the
|
||||
# 'jsb <jsbPreserveNewlines>' parameter. This string is designed to be shown
|
||||
# in a menu alongside the command name, which is why it should be as short as
|
||||
# possible.
|
||||
jsbPreserveNewlinesDesc=Keep existing line breaks?
|
||||
# the 'jsb <doNotPreserveNewlines>' parameter. This string is designed to be
|
||||
# shown in a menu alongside the command name, which is why it should be as short
|
||||
# as possible.
|
||||
jsbDoNotPreserveNewlinesDesc=Do not preserve line breaks
|
||||
|
||||
# LOCALIZATION NOTE (jsbPreserveNewlinesManual) A fuller description of the
|
||||
# 'jsb <jsbPreserveNewlines>' parameter, displayed when the user asks for help
|
||||
|
@ -854,23 +853,18 @@ jsbJslintHappyManual=When set to true, jslint-stricter mode is enforced
|
|||
# 'jsb <braceStyle>' parameter. This string is designed to be shown
|
||||
# in a menu alongside the command name, which is why it should be as short as
|
||||
# possible.
|
||||
jsbBraceStyleDesc=Collapse, expand, end-expand, expand-strict
|
||||
jsbBraceStyleDesc=Select the coding style of braces
|
||||
|
||||
# LOCALIZATION NOTE (jsbBraceStyleManual) A fuller description of the
|
||||
# 'jsb <braceStyle>' parameter, displayed when the user asks for help
|
||||
# on what it does.
|
||||
jsbBraceStyleManual=The coding style of braces. Either collapse, expand, end-expand or expand-strict
|
||||
jsbBraceStyleManual=<p class="nowrap">The coding style of braces. Select from one of the following:</p><ul><li>collapse<br/><pre>if (x == 1) {\n ...\n} else {\n ...\n}</pre></li><li>expand<br/><pre>if (x == 1)\n{\n ...\n}\nelse\n{\n ...\n}</pre></li><li>end-expand<br/><pre>if (x == 1) {\n ...\n}\nelse {\n ...\n}</pre></li><li>expand-strict<br/><pre>if (x == 1)\n{\n return // This option can break scripts\n {\n a: 1\n };\n} else {\n ...\n}</pre></li></ul>
|
||||
|
||||
# LOCALIZATION NOTE (jsbSpaceBeforeConditionalDesc) A very short description of
|
||||
# the 'jsb <spaceBeforeConditional>' parameter. This string is designed to be
|
||||
# shown in a menu alongside the command name, which is why it should be as short
|
||||
# as possible.
|
||||
jsbSpaceBeforeConditionalDesc=Space before if statements?
|
||||
|
||||
# LOCALIZATION NOTE (jsbSpaceBeforeConditionalManual) A fuller description of
|
||||
# the 'jsb <spaceBeforeConditional>' parameter, displayed when the user asks for
|
||||
# help on what it does.
|
||||
jsbSpaceBeforeConditionalManual=Should a space be added before conditional statements?
|
||||
# LOCALIZATION NOTE (jsbNoSpaceBeforeConditionalDesc) A very short description
|
||||
# of the 'jsb <noSpaceBeforeConditional>' parameter. This string is designed to
|
||||
# be shown in a menu alongside the command name, which is why it should be as
|
||||
# short as possible.
|
||||
jsbNoSpaceBeforeConditionalDesc=No space before conditional statements
|
||||
|
||||
# LOCALIZATION NOTE (jsbUnescapeStringsDesc) A very short description of the
|
||||
# 'jsb <unescapeStrings>' parameter. This string is designed to be shown
|
||||
|
@ -887,6 +881,10 @@ jsbUnescapeStringsManual=Should printable characters in strings encoded in \\xNN
|
|||
# the jsb command.
|
||||
jsbInvalidURL=Please enter a valid URL
|
||||
|
||||
# LOCALIZATION NOTE (jsbOptionsDesc) The title of a set of options to
|
||||
# the 'jsb' command, displayed as a heading to the list of options.
|
||||
jsbOptionsDesc=Options
|
||||
|
||||
# LOCALIZATION NOTE (calllogDesc) A very short description of the
|
||||
# 'calllog' command. This string is designed to be shown in a menu
|
||||
# alongside the command name, which is why it should be as short as possible.
|
||||
|
|
|
@ -2444,6 +2444,12 @@ html|*#gcli-output-frame {
|
|||
0 1px 0 hsla(210,16%,76%,.15);
|
||||
}
|
||||
|
||||
.gclitoolbar-input-node > .textbox-input-box > html|*.textbox-input::-moz-selection {
|
||||
background-color: hsl(210,30%,85%);
|
||||
color: hsl(210,11%,16%);
|
||||
text-shadow: none;
|
||||
}
|
||||
|
||||
.gclitoolbar-complete-node {
|
||||
padding-left: 21px;
|
||||
background-color: transparent;
|
||||
|
|
|
@ -63,10 +63,15 @@
|
|||
.gcli-row-out h4,
|
||||
.gcli-row-out h5,
|
||||
.gcli-row-out th,
|
||||
.gcli-row-out strong {
|
||||
.gcli-row-out strong,
|
||||
.gcli-row-out pre {
|
||||
color: hsl(210,30%,95%);
|
||||
}
|
||||
|
||||
.gcli-row-out pre {
|
||||
font-size: 80%;
|
||||
}
|
||||
|
||||
.gcli-out-shortcut,
|
||||
.gcli-help-synopsis {
|
||||
padding: 0 3px;
|
||||
|
|
|
@ -1,402 +0,0 @@
|
|||
/*
|
||||
* Software License Agreement (BSD License)
|
||||
*
|
||||
* Copyright (c) 2007, Parakey Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use of this software in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above
|
||||
* copyright notice, this list of conditions and the
|
||||
* following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the
|
||||
* following disclaimer in the documentation and/or other
|
||||
* materials provided with the distribution.
|
||||
*
|
||||
* * Neither the name of Parakey Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior
|
||||
* written permission of Parakey Inc.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
|
||||
* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Creator:
|
||||
* Joe Hewitt
|
||||
* Contributors
|
||||
* John J. Barton (IBM Almaden)
|
||||
* Jan Odvarko (Mozilla Corp.)
|
||||
* Max Stepanov (Aptana Inc.)
|
||||
* Rob Campbell (Mozilla Corp.)
|
||||
* Hans Hillen (Paciello Group, Mozilla)
|
||||
* Curtis Bartley (Mozilla Corp.)
|
||||
* Mike Collins (IBM Almaden)
|
||||
* Kevin Decker
|
||||
* Mike Ratcliffe (Comartis AG)
|
||||
* Hernan Rodríguez Colmeiro
|
||||
* Austin Andrews
|
||||
* Christoph Dorn
|
||||
* Steven Roussey (AppCenter Inc, Network54)
|
||||
*/
|
||||
|
||||
html {
|
||||
background-color: -moz-dialog;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
overflow: auto;
|
||||
font-family: Lucida Grande, sans-serif;
|
||||
font-size: 11px;
|
||||
padding-top: 5px;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 17px;
|
||||
border-bottom: 1px solid threedlightshadow;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #0000ff;
|
||||
}
|
||||
|
||||
pre {
|
||||
margin: 0;
|
||||
font: inherit;
|
||||
}
|
||||
|
||||
code {
|
||||
display: block;
|
||||
white-space: pre;
|
||||
}
|
||||
|
||||
/* DOMPlate */
|
||||
|
||||
.objectLink-element,
|
||||
.objectLink-textNode,
|
||||
.objectLink-function,
|
||||
.objectBox-stackTrace,
|
||||
.objectLink-profile {
|
||||
font-family: Menlo, Andale Mono, monospace;
|
||||
}
|
||||
|
||||
.objectLink-textNode {
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
|
||||
.objectLink-styleRule,
|
||||
.objectLink-element,
|
||||
.objectLink-textNode {
|
||||
color: #000088;
|
||||
}
|
||||
|
||||
.selectorTag,
|
||||
.selectorId,
|
||||
.selectorClass {
|
||||
font-family: Menlo, Andale Mono, monospace;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.selectorTag {
|
||||
color: #0000FF;
|
||||
}
|
||||
|
||||
.selectorId {
|
||||
color: DarkBlue;
|
||||
}
|
||||
|
||||
.selectorClass {
|
||||
color: red;
|
||||
}
|
||||
|
||||
.selectorHidden > .selectorTag {
|
||||
color: #5F82D9;
|
||||
}
|
||||
|
||||
.selectorHidden > .selectorId {
|
||||
color: #888888;
|
||||
}
|
||||
|
||||
.selectorHidden > .selectorClass {
|
||||
color: #D86060;
|
||||
}
|
||||
|
||||
.selectorValue {
|
||||
font-family: Menlo, Andale Mono, monospace;
|
||||
font-style: italic;
|
||||
color: #555555;
|
||||
}
|
||||
|
||||
.panelNode-html {
|
||||
-moz-box-sizing: padding-box;
|
||||
padding: 4px 0 0 2px;
|
||||
}
|
||||
|
||||
.nodeBox {
|
||||
position: relative;
|
||||
font-family: Menlo, Andale Mono, monospace;
|
||||
padding-left: 13px;
|
||||
-moz-user-select: -moz-none;
|
||||
}
|
||||
|
||||
.nodeBox.search-selection {
|
||||
-moz-user-select: text;
|
||||
}
|
||||
|
||||
.twisty {
|
||||
position: absolute;
|
||||
left: 0px;
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
.nodeChildBox {
|
||||
margin-left: 12px;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.nodeLabel,
|
||||
.nodeCloseLabel {
|
||||
margin: -2px 2px 0 2px;
|
||||
border: 2px solid transparent;
|
||||
border-radius: 3px;
|
||||
padding: 0 2px;
|
||||
color: #000088;
|
||||
}
|
||||
|
||||
.nodeCloseLabel {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.nodeTag {
|
||||
cursor: pointer;
|
||||
color: blue;
|
||||
}
|
||||
|
||||
.nodeValue {
|
||||
color: #FF0000;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.nodeText,
|
||||
.nodeComment {
|
||||
margin: 0 2px;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.nodeText {
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.docType {
|
||||
position: absolute;
|
||||
/* position DOCTYPE element above/outside the "nodeBox" that contains it */
|
||||
/* Note: to be fixed in Bug #688439 */
|
||||
top: -16px;
|
||||
font-family: Menlo, Andale Mono, monospace;
|
||||
padding-left: 8px;
|
||||
color: #999;
|
||||
white-space: nowrap;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.htmlNodeBox {
|
||||
/* make room for DOCTYPE element to be rendered above/outside "nodeBox" */
|
||||
/* Note: to be fixed in Bug #688439 */
|
||||
margin-top: 16px;
|
||||
}
|
||||
|
||||
.nodeWhiteSpace {
|
||||
border: 1px solid LightGray;
|
||||
white-space: pre; /* otherwise the border will be collapsed around zero pixels */
|
||||
margin-left: 1px;
|
||||
color: gray;
|
||||
}
|
||||
|
||||
.nodeWhiteSpace_Space {
|
||||
border: 1px solid #ddd;
|
||||
}
|
||||
|
||||
.nodeTextEntity {
|
||||
border: 1px solid gray;
|
||||
white-space: pre; /* otherwise the border will be collapsed around zero pixels */
|
||||
margin-left: 1px;
|
||||
}
|
||||
|
||||
.nodeComment {
|
||||
color: DarkGreen;
|
||||
}
|
||||
|
||||
.nodeBox.highlightOpen > .nodeLabel {
|
||||
background-color: #EEEEEE;
|
||||
}
|
||||
|
||||
.nodeBox.highlightOpen > .nodeCloseLabel,
|
||||
.nodeBox.highlightOpen > .nodeChildBox,
|
||||
.nodeBox.open > .nodeCloseLabel,
|
||||
.nodeBox.open > .nodeChildBox {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.nodeBox.selected > .nodeLabel > .nodeLabelBox,
|
||||
.nodeBox.selected > .nodeLabel {
|
||||
border-color: Highlight;
|
||||
background-color: Highlight;
|
||||
color: HighlightText !important;
|
||||
}
|
||||
|
||||
.nodeBox.selected > .nodeLabel > .nodeLabelBox,
|
||||
.nodeBox.selected > .nodeLabel > .nodeLabelBox > .nodeTag,
|
||||
.nodeBox.selected > .nodeLabel > .nodeLabelBox > .nodeAttr > .nodeValue,
|
||||
.nodeBox.selected > .nodeLabel > .nodeLabelBox > .nodeText {
|
||||
color: inherit !important;
|
||||
}
|
||||
|
||||
.nodeBox.highlighted > .nodeLabel {
|
||||
border-color: Highlight !important;
|
||||
background-color: cyan !important;
|
||||
color: #000000 !important;
|
||||
}
|
||||
|
||||
.nodeBox.highlighted > .nodeLabel > .nodeLabelBox,
|
||||
.nodeBox.highlighted > .nodeLabel > .nodeLabelBox > .nodeTag,
|
||||
.nodeBox.highlighted > .nodeLabel > .nodeLabelBox > .nodeAttr > .nodeValue,
|
||||
.nodeBox.highlighted > .nodeLabel > .nodeLabelBox > .nodeText {
|
||||
color: #000000 !important;
|
||||
}
|
||||
|
||||
.nodeBox.nodeHidden .nodeLabel > .nodeLabelBox,
|
||||
.nodeBox.nodeHidden .nodeCloseLabel,
|
||||
.nodeBox.nodeHidden .nodeLabel > .nodeLabelBox > .nodeText,
|
||||
.nodeBox.nodeHidden .nodeText {
|
||||
color: #888888;
|
||||
}
|
||||
|
||||
.nodeBox.nodeHidden .nodeLabel > .nodeLabelBox > .nodeTag,
|
||||
.nodeBox.nodeHidden .nodeCloseLabel > .nodeCloseLabelBox > .nodeTag {
|
||||
color: #5F82D9;
|
||||
}
|
||||
|
||||
.nodeBox.nodeHidden .nodeLabel > .nodeLabelBox > .nodeAttr > .nodeValue {
|
||||
color: #D86060;
|
||||
}
|
||||
|
||||
.nodeBox.nodeHidden.selected > .nodeLabel > .nodeLabelBox,
|
||||
.nodeBox.nodeHidden.selected > .nodeLabel > .nodeLabelBox > .nodeTag,
|
||||
.nodeBox.nodeHidden.selected > .nodeLabel > .nodeLabelBox > .nodeAttr > .nodeValue,
|
||||
.nodeBox.nodeHidden.selected > .nodeLabel > .nodeLabelBox > .nodeText {
|
||||
color: SkyBlue !important;
|
||||
}
|
||||
|
||||
.nodeBox.mutated > .nodeLabel,
|
||||
.nodeAttr.mutated,
|
||||
.nodeValue.mutated,
|
||||
.nodeText.mutated,
|
||||
.nodeBox.mutated > .nodeText {
|
||||
background-color: #EFFF79;
|
||||
color: #FF0000 !important;
|
||||
}
|
||||
|
||||
.nodeBox.selected.mutated > .nodeLabel,
|
||||
.nodeBox.selected.mutated > .nodeLabel > .nodeLabelBox,
|
||||
.nodeBox.selected > .nodeLabel > .nodeLabelBox > .nodeAttr.mutated > .nodeValue,
|
||||
.nodeBox.selected > .nodeLabel > .nodeLabelBox > .nodeAttr > .nodeValue.mutated,
|
||||
.nodeBox.selected > .nodeLabel > .nodeLabelBox > .nodeText.mutated {
|
||||
background-color: #EFFF79;
|
||||
border-color: #EFFF79;
|
||||
color: #FF0000 !important;
|
||||
}
|
||||
|
||||
.logRow-dirxml {
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
.soloElement > .nodeBox {
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
.useA11y .nodeLabel.focused {
|
||||
outline: 2px solid #FF9933;
|
||||
-moz-outline-radius: 3px;
|
||||
outline-offset: -2px;
|
||||
}
|
||||
|
||||
.useA11y .nodeLabelBox:focus {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
/* from panel.css */
|
||||
|
||||
/* HTML panel */
|
||||
|
||||
.nodeBox.selected > .nodeLabel > .nodeLabelBox,
|
||||
.nodeBox.selected > .nodeLabel {
|
||||
border-color: #3875d7;
|
||||
background-color: #3875d7;
|
||||
color: #FFFFFF !important;
|
||||
}
|
||||
|
||||
.nodeBox.highlighted > .nodeLabel {
|
||||
border-color: #3875d7 !important;
|
||||
}
|
||||
|
||||
/************************************************************************************************/
|
||||
/* Twisties */
|
||||
|
||||
.twisty
|
||||
{
|
||||
-moz-appearance: treetwisty;
|
||||
}
|
||||
|
||||
.nodeBox.highlightOpen > .nodeLabel > .twisty,
|
||||
.nodeBox.open > .nodeLabel > .twisty
|
||||
{
|
||||
-moz-appearance: treetwistyopen;
|
||||
}
|
||||
|
||||
/************************************************************************************************/
|
||||
/* HTML panel */
|
||||
|
||||
.nodeBox.selected > .nodeLabel > .nodeLabelBox,
|
||||
.nodeBox.selected > .nodeLabel {
|
||||
border-color: #3875d7;
|
||||
background-color: #3875d7;
|
||||
color: #FFFFFF !important;
|
||||
}
|
||||
|
||||
.nodeBox.highlighted > .nodeLabel {
|
||||
border-color: #3875d7 !important;
|
||||
}
|
||||
|
||||
.editingAttributeValue {
|
||||
background-color: #492;
|
||||
}
|
||||
|
||||
#attribute-editor {
|
||||
visibility: hidden;
|
||||
position: absolute;
|
||||
z-index: 5000;
|
||||
background-color: #fff;
|
||||
border: 1px solid #000;
|
||||
}
|
||||
|
||||
#attribute-editor.editing {
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
#attribute-editor-input {
|
||||
border: none;
|
||||
padding: 2px 5px;
|
||||
font-family: Menlo, Andale Mono, monospace;
|
||||
font-size: 11px;
|
||||
}
|
|
@ -110,7 +110,6 @@ browser.jar:
|
|||
skin/classic/browser/devtools/webconsole_networkpanel.css (devtools/webconsole_networkpanel.css)
|
||||
skin/classic/browser/devtools/webconsole.png (devtools/webconsole.png)
|
||||
skin/classic/browser/devtools/commandline.css (devtools/commandline.css)
|
||||
skin/classic/browser/devtools/htmlpanel.css (devtools/htmlpanel.css)
|
||||
skin/classic/browser/devtools/markup-view.css (devtools/markup-view.css)
|
||||
skin/classic/browser/devtools/orion.css (devtools/orion.css)
|
||||
skin/classic/browser/devtools/orion-container.css (devtools/orion-container.css)
|
||||
|
|
|
@ -3866,6 +3866,12 @@ html|*#gcli-output-frame {
|
|||
0 1px 0 hsla(210,16%,76%,.15);
|
||||
}
|
||||
|
||||
.gclitoolbar-input-node > .textbox-input-box > html|*.textbox-input::-moz-selection {
|
||||
background-color: hsl(210,30%,85%);
|
||||
color: hsl(210,11%,16%);
|
||||
text-shadow: none;
|
||||
}
|
||||
|
||||
.gclitoolbar-complete-node {
|
||||
padding-left: 21px;
|
||||
background-color: transparent;
|
||||
|
|
|
@ -65,10 +65,15 @@
|
|||
.gcli-row-out h4,
|
||||
.gcli-row-out h5,
|
||||
.gcli-row-out th,
|
||||
.gcli-row-out strong {
|
||||
.gcli-row-out strong,
|
||||
.gcli-row-out pre {
|
||||
color: hsl(210,30%,95%);
|
||||
}
|
||||
|
||||
.gcli-row-out pre {
|
||||
font-size: 80%;
|
||||
}
|
||||
|
||||
.gcli-out-shortcut,
|
||||
.gcli-help-synopsis {
|
||||
padding: 0 3px;
|
||||
|
|
|
@ -1,392 +0,0 @@
|
|||
/*
|
||||
* Software License Agreement (BSD License)
|
||||
*
|
||||
* Copyright (c) 2007, Parakey Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use of this software in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above
|
||||
* copyright notice, this list of conditions and the
|
||||
* following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the
|
||||
* following disclaimer in the documentation and/or other
|
||||
* materials provided with the distribution.
|
||||
*
|
||||
* * Neither the name of Parakey Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior
|
||||
* written permission of Parakey Inc.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
|
||||
* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Creator:
|
||||
* Joe Hewitt
|
||||
* Contributors
|
||||
* John J. Barton (IBM Almaden)
|
||||
* Jan Odvarko (Mozilla Corp.)
|
||||
* Max Stepanov (Aptana Inc.)
|
||||
* Rob Campbell (Mozilla Corp.)
|
||||
* Hans Hillen (Paciello Group, Mozilla)
|
||||
* Curtis Bartley (Mozilla Corp.)
|
||||
* Mike Collins (IBM Almaden)
|
||||
* Kevin Decker
|
||||
* Mike Ratcliffe (Comartis AG)
|
||||
* Hernan Rodríguez Colmeiro
|
||||
* Austin Andrews
|
||||
* Christoph Dorn
|
||||
* Steven Roussey (AppCenter Inc, Network54)
|
||||
*/
|
||||
|
||||
html {
|
||||
background-color: -moz-dialog;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
overflow: auto;
|
||||
font-family: Lucida Grande, sans-serif;
|
||||
font-size: 11px;
|
||||
padding-top: 5px;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 17px;
|
||||
border-bottom: 1px solid threedlightshadow;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #0000ff;
|
||||
}
|
||||
|
||||
pre {
|
||||
margin: 0;
|
||||
font: inherit;
|
||||
}
|
||||
|
||||
code {
|
||||
display: block;
|
||||
white-space: pre;
|
||||
}
|
||||
|
||||
/* DOMPlate */
|
||||
|
||||
.objectLink-element,
|
||||
.objectLink-textNode,
|
||||
.objectLink-function,
|
||||
.objectBox-stackTrace,
|
||||
.objectLink-profile {
|
||||
font-family: Menlo, Andale Mono, monospace;
|
||||
}
|
||||
|
||||
.objectLink-textNode {
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
|
||||
.objectLink-styleRule,
|
||||
.objectLink-element,
|
||||
.objectLink-textNode {
|
||||
color: #000088;
|
||||
}
|
||||
|
||||
.selectorTag,
|
||||
.selectorId,
|
||||
.selectorClass {
|
||||
font-family: Menlo, Andale Mono, monospace;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.selectorTag {
|
||||
color: #0000FF;
|
||||
}
|
||||
|
||||
.selectorId {
|
||||
color: DarkBlue;
|
||||
}
|
||||
|
||||
.selectorClass {
|
||||
color: red;
|
||||
}
|
||||
|
||||
.selectorHidden > .selectorTag {
|
||||
color: #5F82D9;
|
||||
}
|
||||
|
||||
.selectorHidden > .selectorId {
|
||||
color: #888888;
|
||||
}
|
||||
|
||||
.selectorHidden > .selectorClass {
|
||||
color: #D86060;
|
||||
}
|
||||
|
||||
.selectorValue {
|
||||
font-family: Menlo, Andale Mono, monospace;
|
||||
font-style: italic;
|
||||
color: #555555;
|
||||
}
|
||||
|
||||
.panelNode-html {
|
||||
-moz-box-sizing: padding-box;
|
||||
padding: 4px 0 0 2px;
|
||||
}
|
||||
|
||||
.nodeBox {
|
||||
position: relative;
|
||||
font-family: Menlo, Andale Mono, monospace;
|
||||
padding-left: 13px;
|
||||
-moz-user-select: -moz-none;
|
||||
}
|
||||
|
||||
.nodeBox.search-selection {
|
||||
-moz-user-select: text;
|
||||
}
|
||||
|
||||
.twisty {
|
||||
position: absolute;
|
||||
left: 0px;
|
||||
top: 0px;
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
}
|
||||
|
||||
.nodeChildBox {
|
||||
margin-left: 12px;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.nodeLabel,
|
||||
.nodeCloseLabel {
|
||||
margin: -2px 2px 0 2px;
|
||||
border: 2px solid transparent;
|
||||
border-radius: 3px;
|
||||
padding: 0 2px;
|
||||
color: #000088;
|
||||
}
|
||||
|
||||
.nodeCloseLabel {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.nodeTag {
|
||||
cursor: pointer;
|
||||
color: blue;
|
||||
}
|
||||
|
||||
.nodeValue {
|
||||
color: #FF0000;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.nodeText,
|
||||
.nodeComment {
|
||||
margin: 0 2px;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.nodeText {
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.docType {
|
||||
position: absolute;
|
||||
/* position DOCTYPE element above/outside the "nodeBox" that contains it */
|
||||
/* Note: to be fixed in Bug #688439 */
|
||||
top: -16px;
|
||||
font-family: Menlo, Andale Mono, monospace;
|
||||
padding-left: 8px;
|
||||
color: #999;
|
||||
white-space: nowrap;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.htmlNodeBox {
|
||||
/* make room for DOCTYPE element to be rendered above/outside "nodeBox" */
|
||||
/* Note: to be fixed in Bug #688439 */
|
||||
margin-top: 16px;
|
||||
}
|
||||
|
||||
.nodeWhiteSpace {
|
||||
border: 1px solid LightGray;
|
||||
white-space: pre; /* otherwise the border will be collapsed around zero pixels */
|
||||
margin-left: 1px;
|
||||
color: gray;
|
||||
}
|
||||
|
||||
.nodeWhiteSpace_Space {
|
||||
border: 1px solid #ddd;
|
||||
}
|
||||
|
||||
.nodeTextEntity {
|
||||
border: 1px solid gray;
|
||||
white-space: pre; /* otherwise the border will be collapsed around zero pixels */
|
||||
margin-left: 1px;
|
||||
}
|
||||
|
||||
.nodeComment {
|
||||
color: DarkGreen;
|
||||
}
|
||||
|
||||
.nodeBox.highlightOpen > .nodeLabel {
|
||||
background-color: #EEEEEE;
|
||||
}
|
||||
|
||||
.nodeBox.highlightOpen > .nodeCloseLabel,
|
||||
.nodeBox.highlightOpen > .nodeChildBox,
|
||||
.nodeBox.open > .nodeCloseLabel,
|
||||
.nodeBox.open > .nodeChildBox {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.nodeBox.selected > .nodeLabel > .nodeLabelBox,
|
||||
.nodeBox.selected > .nodeLabel {
|
||||
border-color: Highlight;
|
||||
background-color: Highlight;
|
||||
color: HighlightText !important;
|
||||
}
|
||||
|
||||
.nodeBox.selected > .nodeLabel > .nodeLabelBox,
|
||||
.nodeBox.selected > .nodeLabel > .nodeLabelBox > .nodeTag,
|
||||
.nodeBox.selected > .nodeLabel > .nodeLabelBox > .nodeAttr > .nodeValue,
|
||||
.nodeBox.selected > .nodeLabel > .nodeLabelBox > .nodeText {
|
||||
color: inherit !important;
|
||||
}
|
||||
|
||||
.nodeBox.highlighted > .nodeLabel {
|
||||
border-color: Highlight !important;
|
||||
background-color: cyan !important;
|
||||
color: #000000 !important;
|
||||
}
|
||||
|
||||
.nodeBox.highlighted > .nodeLabel > .nodeLabelBox,
|
||||
.nodeBox.highlighted > .nodeLabel > .nodeLabelBox > .nodeTag,
|
||||
.nodeBox.highlighted > .nodeLabel > .nodeLabelBox > .nodeAttr > .nodeValue,
|
||||
.nodeBox.highlighted > .nodeLabel > .nodeLabelBox > .nodeText {
|
||||
color: #000000 !important;
|
||||
}
|
||||
|
||||
.nodeBox.nodeHidden .nodeLabel > .nodeLabelBox,
|
||||
.nodeBox.nodeHidden .nodeCloseLabel,
|
||||
.nodeBox.nodeHidden .nodeLabel > .nodeLabelBox > .nodeText,
|
||||
.nodeBox.nodeHidden .nodeText {
|
||||
color: #888888;
|
||||
}
|
||||
|
||||
.nodeBox.nodeHidden .nodeLabel > .nodeLabelBox > .nodeTag,
|
||||
.nodeBox.nodeHidden .nodeCloseLabel > .nodeCloseLabelBox > .nodeTag {
|
||||
color: #5F82D9;
|
||||
}
|
||||
|
||||
.nodeBox.nodeHidden .nodeLabel > .nodeLabelBox > .nodeAttr > .nodeValue {
|
||||
color: #D86060;
|
||||
}
|
||||
|
||||
.nodeBox.nodeHidden.selected > .nodeLabel > .nodeLabelBox,
|
||||
.nodeBox.nodeHidden.selected > .nodeLabel > .nodeLabelBox > .nodeTag,
|
||||
.nodeBox.nodeHidden.selected > .nodeLabel > .nodeLabelBox > .nodeAttr > .nodeValue,
|
||||
.nodeBox.nodeHidden.selected > .nodeLabel > .nodeLabelBox > .nodeText {
|
||||
color: SkyBlue !important;
|
||||
}
|
||||
|
||||
.nodeBox.mutated > .nodeLabel,
|
||||
.nodeAttr.mutated,
|
||||
.nodeValue.mutated,
|
||||
.nodeText.mutated,
|
||||
.nodeBox.mutated > .nodeText {
|
||||
background-color: #EFFF79;
|
||||
color: #FF0000 !important;
|
||||
}
|
||||
|
||||
.nodeBox.selected.mutated > .nodeLabel,
|
||||
.nodeBox.selected.mutated > .nodeLabel > .nodeLabelBox,
|
||||
.nodeBox.selected > .nodeLabel > .nodeLabelBox > .nodeAttr.mutated > .nodeValue,
|
||||
.nodeBox.selected > .nodeLabel > .nodeLabelBox > .nodeAttr > .nodeValue.mutated,
|
||||
.nodeBox.selected > .nodeLabel > .nodeLabelBox > .nodeText.mutated {
|
||||
background-color: #EFFF79;
|
||||
border-color: #EFFF79;
|
||||
color: #FF0000 !important;
|
||||
}
|
||||
|
||||
.logRow-dirxml {
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
.soloElement > .nodeBox {
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
.nodeBox.selected > .nodeLabel > .nodeLabelBox,
|
||||
.nodeBox.selected > .nodeLabel {
|
||||
border-color: #3875d7;
|
||||
background-color: #3875d7;
|
||||
color: #FFFFFF !important;
|
||||
}
|
||||
|
||||
.nodeBox.highlighted > .nodeLabel {
|
||||
border-color: #3875d7 !important;
|
||||
}
|
||||
|
||||
/************************************************************************************************/
|
||||
/* Twisties */
|
||||
|
||||
.twisty
|
||||
{
|
||||
-moz-appearance: treetwisty;
|
||||
}
|
||||
|
||||
.nodeBox.highlightOpen > .nodeLabel > .twisty,
|
||||
.nodeBox.open > .nodeLabel > .twisty
|
||||
{
|
||||
-moz-appearance: treetwistyopen;
|
||||
}
|
||||
|
||||
.memberRow.hasChildren > .memberLabelCell > .memberLabel,
|
||||
.hasHeaders .netHrefLabel {
|
||||
background-position: 2px 2px;
|
||||
}
|
||||
|
||||
.nodeBox.selected > .nodeLabel > .nodeLabelBox,
|
||||
.nodeBox.selected > .nodeLabel {
|
||||
border-color: #3875d7;
|
||||
background-color: #3875d7;
|
||||
color: #FFFFFF !important;
|
||||
}
|
||||
|
||||
.nodeBox.highlighted > .nodeLabel {
|
||||
border-color: #3875d7 !important;
|
||||
}
|
||||
|
||||
.editingAttributeValue {
|
||||
background-color: #492;
|
||||
}
|
||||
|
||||
#attribute-editor {
|
||||
visibility: hidden;
|
||||
position: absolute;
|
||||
z-index: 5000;
|
||||
background-color: #fff;
|
||||
border: 1px solid #000;
|
||||
}
|
||||
|
||||
#attribute-editor.editing {
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
#attribute-editor-input {
|
||||
border: none;
|
||||
padding: 2px 5px;
|
||||
font-family: Menlo, Andale Mono, monospace;
|
||||
font-size: 11px;
|
||||
}
|
|
@ -175,7 +175,6 @@ browser.jar:
|
|||
skin/classic/browser/devtools/goto-mdn.png (devtools/goto-mdn.png)
|
||||
skin/classic/browser/devtools/csshtmltree.css (devtools/csshtmltree.css)
|
||||
skin/classic/browser/devtools/commandline.css (devtools/commandline.css)
|
||||
skin/classic/browser/devtools/htmlpanel.css (devtools/htmlpanel.css)
|
||||
skin/classic/browser/devtools/markup-view.css (devtools/markup-view.css)
|
||||
skin/classic/browser/devtools/orion.css (devtools/orion.css)
|
||||
skin/classic/browser/devtools/orion-container.css (devtools/orion-container.css)
|
||||
|
|
|
@ -3125,6 +3125,12 @@ html|*#gcli-output-frame {
|
|||
0 0 0 1px hsla(210,40%,83%,.1);
|
||||
}
|
||||
|
||||
.gclitoolbar-input-node > .textbox-input-box > html|*.textbox-input::-moz-selection {
|
||||
background-color: hsl(210,30%,85%);
|
||||
color: hsl(210,24%,16%);
|
||||
text-shadow: none;
|
||||
}
|
||||
|
||||
.gclitoolbar-complete-node {
|
||||
padding-left: 21px;
|
||||
background-color: transparent;
|
||||
|
|
|
@ -63,10 +63,15 @@
|
|||
.gcli-row-out h4,
|
||||
.gcli-row-out h5,
|
||||
.gcli-row-out th,
|
||||
.gcli-row-out strong {
|
||||
.gcli-row-out strong,
|
||||
.gcli-row-out pre {
|
||||
color: hsl(210,30%,95%);
|
||||
}
|
||||
|
||||
.gcli-row-out pre {
|
||||
font-size: 80%;
|
||||
}
|
||||
|
||||
.gcli-out-shortcut,
|
||||
.gcli-help-synopsis {
|
||||
padding: 0 3px;
|
||||
|
|
|
@ -1,377 +0,0 @@
|
|||
/*
|
||||
* Software License Agreement (BSD License)
|
||||
*
|
||||
* Copyright (c) 2007, Parakey Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use of this software in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above
|
||||
* copyright notice, this list of conditions and the
|
||||
* following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the
|
||||
* following disclaimer in the documentation and/or other
|
||||
* materials provided with the distribution.
|
||||
*
|
||||
* * Neither the name of Parakey Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior
|
||||
* written permission of Parakey Inc.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
|
||||
* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Creator:
|
||||
* Joe Hewitt
|
||||
* Contributors
|
||||
* John J. Barton (IBM Almaden)
|
||||
* Jan Odvarko (Mozilla Corp.)
|
||||
* Max Stepanov (Aptana Inc.)
|
||||
* Rob Campbell (Mozilla Corp.)
|
||||
* Hans Hillen (Paciello Group, Mozilla)
|
||||
* Curtis Bartley (Mozilla Corp.)
|
||||
* Mike Collins (IBM Almaden)
|
||||
* Kevin Decker
|
||||
* Mike Ratcliffe (Comartis AG)
|
||||
* Hernan Rodríguez Colmeiro
|
||||
* Austin Andrews
|
||||
* Christoph Dorn
|
||||
* Steven Roussey (AppCenter Inc, Network54)
|
||||
*/
|
||||
|
||||
html {
|
||||
background-color: -moz-dialog;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
overflow: auto;
|
||||
font-family: Lucida Grande, sans-serif;
|
||||
font-size: 11px;
|
||||
padding-top: 5px;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 17px;
|
||||
border-bottom: 1px solid threedlightshadow;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #0000ff;
|
||||
}
|
||||
|
||||
pre {
|
||||
margin: 0;
|
||||
font: inherit;
|
||||
}
|
||||
|
||||
code {
|
||||
display: block;
|
||||
white-space: pre;
|
||||
}
|
||||
|
||||
/* DOMPlate */
|
||||
|
||||
.objectLink-element,
|
||||
.objectLink-textNode,
|
||||
.objectLink-function,
|
||||
.objectBox-stackTrace,
|
||||
.objectLink-profile {
|
||||
font-family: Menlo, Andale Mono, monospace;
|
||||
}
|
||||
|
||||
.objectLink-textNode {
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
|
||||
.objectLink-styleRule,
|
||||
.objectLink-element,
|
||||
.objectLink-textNode {
|
||||
color: #000088;
|
||||
}
|
||||
|
||||
.selectorTag,
|
||||
.selectorId,
|
||||
.selectorClass {
|
||||
font-family: Menlo, Andale Mono, monospace;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.selectorTag {
|
||||
color: #0000FF;
|
||||
}
|
||||
|
||||
.selectorId {
|
||||
color: DarkBlue;
|
||||
}
|
||||
|
||||
.selectorClass {
|
||||
color: red;
|
||||
}
|
||||
|
||||
.selectorHidden > .selectorTag {
|
||||
color: #5F82D9;
|
||||
}
|
||||
|
||||
.selectorHidden > .selectorId {
|
||||
color: #888888;
|
||||
}
|
||||
|
||||
.selectorHidden > .selectorClass {
|
||||
color: #D86060;
|
||||
}
|
||||
|
||||
.selectorValue {
|
||||
font-family: Menlo, Andale Mono, monospace;
|
||||
font-style: italic;
|
||||
color: #555555;
|
||||
}
|
||||
|
||||
.panelNode-html {
|
||||
-moz-box-sizing: padding-box;
|
||||
padding: 4px 0 0 2px;
|
||||
}
|
||||
|
||||
.nodeBox {
|
||||
position: relative;
|
||||
font-family: Menlo, Andale Mono, monospace;
|
||||
padding-left: 13px;
|
||||
-moz-user-select: -moz-none;
|
||||
}
|
||||
|
||||
.nodeBox.search-selection {
|
||||
-moz-user-select: text;
|
||||
}
|
||||
|
||||
.twisty {
|
||||
position: absolute;
|
||||
left: 0px;
|
||||
top: 0px;
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
}
|
||||
|
||||
.nodeChildBox {
|
||||
margin-left: 12px;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.nodeLabel,
|
||||
.nodeCloseLabel {
|
||||
margin: -2px 2px 0 2px;
|
||||
border: 2px solid transparent;
|
||||
border-radius: 3px;
|
||||
padding: 0 2px;
|
||||
color: #000088;
|
||||
}
|
||||
|
||||
.nodeCloseLabel {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.nodeTag {
|
||||
cursor: pointer;
|
||||
color: blue;
|
||||
}
|
||||
|
||||
.nodeValue {
|
||||
color: #FF0000;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.nodeText,
|
||||
.nodeComment {
|
||||
margin: 0 2px;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.nodeText {
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.docType {
|
||||
position: absolute;
|
||||
/* position DOCTYPE element above/outside the "nodeBox" that contains it */
|
||||
/* Note: to be fixed in Bug #688439 */
|
||||
top: -16px;
|
||||
font-family: Menlo, Andale Mono, monospace;
|
||||
padding-left: 8px;
|
||||
color: #999;
|
||||
white-space: nowrap;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.htmlNodeBox {
|
||||
/* make room for DOCTYPE element to be rendered above/outside "nodeBox" */
|
||||
/* Note: to be fixed in Bug #688439 */
|
||||
margin-top: 16px;
|
||||
}
|
||||
|
||||
.nodeWhiteSpace {
|
||||
border: 1px solid LightGray;
|
||||
white-space: pre;
|
||||
margin-left: 1px;
|
||||
color: gray;
|
||||
}
|
||||
|
||||
.nodeWhiteSpace_Space {
|
||||
border: 1px solid #ddd;
|
||||
}
|
||||
|
||||
.nodeTextEntity {
|
||||
border: 1px solid gray;
|
||||
white-space: pre;
|
||||
margin-left: 1px;
|
||||
}
|
||||
|
||||
.nodeComment {
|
||||
color: DarkGreen;
|
||||
}
|
||||
|
||||
.nodeBox.highlightOpen > .nodeLabel {
|
||||
background-color: #EEEEEE;
|
||||
}
|
||||
|
||||
.nodeBox.highlightOpen > .nodeCloseLabel,
|
||||
.nodeBox.highlightOpen > .nodeChildBox,
|
||||
.nodeBox.open > .nodeCloseLabel,
|
||||
.nodeBox.open > .nodeChildBox {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.nodeBox.selected > .nodeLabel > .nodeLabelBox,
|
||||
.nodeBox.selected > .nodeLabel {
|
||||
border-color: Highlight;
|
||||
background-color: Highlight;
|
||||
color: HighlightText !important;
|
||||
}
|
||||
|
||||
.nodeBox.selected > .nodeLabel > .nodeLabelBox,
|
||||
.nodeBox.selected > .nodeLabel > .nodeLabelBox > .nodeTag,
|
||||
.nodeBox.selected > .nodeLabel > .nodeLabelBox > .nodeAttr > .nodeValue,
|
||||
.nodeBox.selected > .nodeLabel > .nodeLabelBox > .nodeText {
|
||||
color: inherit !important;
|
||||
}
|
||||
|
||||
.nodeBox.highlighted > .nodeLabel {
|
||||
border-color: Highlight !important;
|
||||
background-color: cyan !important;
|
||||
color: #000000 !important;
|
||||
}
|
||||
|
||||
.nodeBox.highlighted > .nodeLabel > .nodeLabelBox,
|
||||
.nodeBox.highlighted > .nodeLabel > .nodeLabelBox > .nodeTag,
|
||||
.nodeBox.highlighted > .nodeLabel > .nodeLabelBox > .nodeAttr > .nodeValue,
|
||||
.nodeBox.highlighted > .nodeLabel > .nodeLabelBox > .nodeText {
|
||||
color: #000000 !important;
|
||||
}
|
||||
|
||||
.nodeBox.nodeHidden .nodeLabel > .nodeLabelBox,
|
||||
.nodeBox.nodeHidden .nodeCloseLabel,
|
||||
.nodeBox.nodeHidden .nodeLabel > .nodeLabelBox > .nodeText,
|
||||
.nodeBox.nodeHidden .nodeText {
|
||||
color: #888888;
|
||||
}
|
||||
|
||||
.nodeBox.nodeHidden .nodeLabel > .nodeLabelBox > .nodeTag,
|
||||
.nodeBox.nodeHidden .nodeCloseLabel > .nodeCloseLabelBox > .nodeTag {
|
||||
color: #5F82D9;
|
||||
}
|
||||
|
||||
.nodeBox.nodeHidden .nodeLabel > .nodeLabelBox > .nodeAttr > .nodeValue {
|
||||
color: #D86060;
|
||||
}
|
||||
|
||||
.nodeBox.nodeHidden.selected > .nodeLabel > .nodeLabelBox,
|
||||
.nodeBox.nodeHidden.selected > .nodeLabel > .nodeLabelBox > .nodeTag,
|
||||
.nodeBox.nodeHidden.selected > .nodeLabel > .nodeLabelBox > .nodeAttr > .nodeValue,
|
||||
.nodeBox.nodeHidden.selected > .nodeLabel > .nodeLabelBox > .nodeText {
|
||||
color: SkyBlue !important;
|
||||
}
|
||||
|
||||
.nodeBox.mutated > .nodeLabel,
|
||||
.nodeAttr.mutated,
|
||||
.nodeValue.mutated,
|
||||
.nodeText.mutated,
|
||||
.nodeBox.mutated > .nodeText {
|
||||
background-color: #EFFF79;
|
||||
color: #FF0000 !important;
|
||||
}
|
||||
|
||||
.nodeBox.selected.mutated > .nodeLabel,
|
||||
.nodeBox.selected.mutated > .nodeLabel > .nodeLabelBox,
|
||||
.nodeBox.selected > .nodeLabel > .nodeLabelBox > .nodeAttr.mutated > .nodeValue,
|
||||
.nodeBox.selected > .nodeLabel > .nodeLabelBox > .nodeAttr > .nodeValue.mutated,
|
||||
.nodeBox.selected > .nodeLabel > .nodeLabelBox > .nodeText.mutated {
|
||||
background-color: #EFFF79;
|
||||
border-color: #EFFF79;
|
||||
color: #FF0000 !important;
|
||||
}
|
||||
|
||||
.logRow-dirxml {
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
.soloElement > .nodeBox {
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
.nodeBox.selected > .nodeLabel > .nodeLabelBox,
|
||||
.nodeBox.selected > .nodeLabel {
|
||||
border-color: #3875d7;
|
||||
background-color: #3875d7;
|
||||
color: #FFFFFF !important;
|
||||
}
|
||||
|
||||
.nodeBox.highlighted > .nodeLabel {
|
||||
border-color: #3875d7 !important;
|
||||
}
|
||||
|
||||
/* Twisties */
|
||||
|
||||
.twisty
|
||||
{
|
||||
background-repeat: no-repeat;
|
||||
background-position: center;
|
||||
background-image: url("chrome://global/skin/tree/twisty-clsd.png") !important;
|
||||
}
|
||||
|
||||
.nodeBox.highlightOpen > .nodeLabel > .twisty,
|
||||
.nodeBox.open > .nodeLabel > .twisty
|
||||
{
|
||||
background-image: url("chrome://global/skin/tree/twisty-open.png") !important;
|
||||
}
|
||||
|
||||
.editingAttributeValue {
|
||||
background-color: #492;
|
||||
}
|
||||
|
||||
#attribute-editor {
|
||||
visibility: hidden;
|
||||
position: absolute;
|
||||
z-index: 5000;
|
||||
background-color: #fff;
|
||||
border: 1px solid #000;
|
||||
}
|
||||
|
||||
#attribute-editor.editing {
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
#attribute-editor-input {
|
||||
border: none;
|
||||
padding: 2px 5px;
|
||||
font-family: Menlo, Andale Mono, monospace;
|
||||
font-size: 11px;
|
||||
}
|
|
@ -133,7 +133,6 @@ browser.jar:
|
|||
skin/classic/browser/devtools/goto-mdn.png (devtools/goto-mdn.png)
|
||||
skin/classic/browser/devtools/csshtmltree.css (devtools/csshtmltree.css)
|
||||
skin/classic/browser/devtools/commandline.css (devtools/commandline.css)
|
||||
skin/classic/browser/devtools/htmlpanel.css (devtools/htmlpanel.css)
|
||||
skin/classic/browser/devtools/markup-view.css (devtools/markup-view.css)
|
||||
skin/classic/browser/devtools/orion.css (devtools/orion.css)
|
||||
skin/classic/browser/devtools/orion-container.css (devtools/orion-container.css)
|
||||
|
@ -339,7 +338,6 @@ browser.jar:
|
|||
skin/classic/aero/browser/devtools/goto-mdn.png (devtools/goto-mdn.png)
|
||||
skin/classic/aero/browser/devtools/csshtmltree.css (devtools/csshtmltree.css)
|
||||
skin/classic/aero/browser/devtools/commandline.css (devtools/commandline.css)
|
||||
skin/classic/aero/browser/devtools/htmlpanel.css (devtools/htmlpanel.css)
|
||||
skin/classic/aero/browser/devtools/markup-view.css (devtools/markup-view.css)
|
||||
skin/classic/aero/browser/devtools/orion.css (devtools/orion.css)
|
||||
skin/classic/aero/browser/devtools/orion-container.css (devtools/orion-container.css)
|
||||
|
|
|
@ -69,17 +69,33 @@ var ConsoleAPIStorage = {
|
|||
},
|
||||
|
||||
/**
|
||||
* Get the events array by inner window ID.
|
||||
* Get the events array by inner window ID or all events from all windows.
|
||||
*
|
||||
* @param string aId
|
||||
* The inner window ID for which you want to get the array of cached
|
||||
* events.
|
||||
* @param string [aId]
|
||||
* Optional, the inner window ID for which you want to get the array of
|
||||
* cached events.
|
||||
* @returns array
|
||||
* The array of cached events for the given window.
|
||||
* The array of cached events for the given window. If no |aId| is
|
||||
* given this function returns all of the cached events, from any
|
||||
* window.
|
||||
*/
|
||||
getEvents: function CS_getEvents(aId)
|
||||
{
|
||||
return (_consoleStorage[aId] || []).slice(0);
|
||||
if (aId != null) {
|
||||
return (_consoleStorage[aId] || []).slice(0);
|
||||
}
|
||||
|
||||
let ids = [];
|
||||
|
||||
for each (let events in _consoleStorage) {
|
||||
ids.push(events);
|
||||
}
|
||||
|
||||
let result = [].concat.apply([], ids);
|
||||
|
||||
return result.sort(function(a, b) {
|
||||
return a.timeStamp - b.timeStamp;
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
|
|
|
@ -12,6 +12,7 @@ include $(topsrcdir)/config/config.mk
|
|||
PARALLEL_DIRS += \
|
||||
debugger \
|
||||
sourcemap \
|
||||
webconsole \
|
||||
$(NULL)
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
|
|
@ -22,6 +22,9 @@ XPCOMUtils.defineLazyServiceGetter(this, "socketTransportService",
|
|||
"@mozilla.org/network/socket-transport-service;1",
|
||||
"nsISocketTransportService");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "WebConsoleClient",
|
||||
"resource://gre/modules/devtools/WebConsoleClient.jsm");
|
||||
|
||||
let wantLogging = Services.prefs.getBoolPref("devtools.debugger.log");
|
||||
|
||||
function dumpn(str)
|
||||
|
@ -164,10 +167,16 @@ const ThreadStateTypes = {
|
|||
* by the client.
|
||||
*/
|
||||
const UnsolicitedNotifications = {
|
||||
"eventNotification": "eventNotification",
|
||||
"consoleAPICall": "consoleAPICall",
|
||||
"fileActivity": "fileActivity",
|
||||
"locationChange": "locationChange",
|
||||
"networkEvent": "networkEvent",
|
||||
"networkEventUpdate": "networkEventUpdate",
|
||||
"newScript": "newScript",
|
||||
"tabDetached": "tabDetached",
|
||||
"tabNavigated": "tabNavigated"
|
||||
"tabNavigated": "tabNavigated",
|
||||
"pageError": "pageError",
|
||||
"profilerStateChanged": "profilerStateChanged"
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -194,6 +203,7 @@ function DebuggerClient(aTransport)
|
|||
this._transport.hooks = this;
|
||||
this._threadClients = {};
|
||||
this._tabClients = {};
|
||||
this._consoleClients = {};
|
||||
|
||||
this._pendingRequests = [];
|
||||
this._activeRequests = {};
|
||||
|
@ -249,10 +259,32 @@ DebuggerClient.prototype = {
|
|||
}
|
||||
}.bind(this);
|
||||
|
||||
if (this.activeThread) {
|
||||
this.activeThread.detach(detachTab);
|
||||
} else {
|
||||
detachTab();
|
||||
let detachThread = function _detachThread() {
|
||||
if (this.activeThread) {
|
||||
this.activeThread.detach(detachTab);
|
||||
} else {
|
||||
detachTab();
|
||||
}
|
||||
}.bind(this);
|
||||
|
||||
let consolesClosed = 0;
|
||||
let consolesToClose = 0;
|
||||
|
||||
let onConsoleClose = function _onConsoleClose() {
|
||||
consolesClosed++;
|
||||
if (consolesClosed >= consolesToClose) {
|
||||
this._consoleClients = {};
|
||||
detachThread();
|
||||
}
|
||||
}.bind(this);
|
||||
|
||||
for each (let client in this._consoleClients) {
|
||||
consolesToClose++;
|
||||
client.close(onConsoleClose);
|
||||
}
|
||||
|
||||
if (!consolesToClose) {
|
||||
detachThread();
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -282,8 +314,9 @@ DebuggerClient.prototype = {
|
|||
let self = this;
|
||||
let packet = { to: aTabActor, type: "attach" };
|
||||
this.request(packet, function(aResponse) {
|
||||
let tabClient;
|
||||
if (!aResponse.error) {
|
||||
var tabClient = new TabClient(self, aTabActor);
|
||||
tabClient = new TabClient(self, aTabActor);
|
||||
self._tabClients[aTabActor] = tabClient;
|
||||
self.activeTab = tabClient;
|
||||
}
|
||||
|
@ -291,6 +324,36 @@ DebuggerClient.prototype = {
|
|||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Attach to a Web Console actor.
|
||||
*
|
||||
* @param string aConsoleActor
|
||||
* The ID for the console actor to attach to.
|
||||
* @param array aListeners
|
||||
* The console listeners you want to start.
|
||||
* @param function aOnResponse
|
||||
* Called with the response packet and a WebConsoleClient
|
||||
* instance (which will be undefined on error).
|
||||
*/
|
||||
attachConsole:
|
||||
function DC_attachConsole(aConsoleActor, aListeners, aOnResponse) {
|
||||
let self = this;
|
||||
let packet = {
|
||||
to: aConsoleActor,
|
||||
type: "startListeners",
|
||||
listeners: aListeners,
|
||||
};
|
||||
|
||||
this.request(packet, function(aResponse) {
|
||||
let consoleClient;
|
||||
if (!aResponse.error) {
|
||||
consoleClient = new WebConsoleClient(self, aConsoleActor);
|
||||
self._consoleClients[aConsoleActor] = consoleClient;
|
||||
}
|
||||
aOnResponse(aResponse, consoleClient);
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Attach to a thread actor.
|
||||
*
|
||||
|
@ -313,6 +376,20 @@ DebuggerClient.prototype = {
|
|||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Release an object actor.
|
||||
*
|
||||
* @param string aActor
|
||||
* The actor ID to send the request to.
|
||||
*/
|
||||
release: function DC_release(aActor) {
|
||||
let packet = {
|
||||
to: aActor,
|
||||
type: "release",
|
||||
};
|
||||
this.request(packet);
|
||||
},
|
||||
|
||||
/**
|
||||
* Send a request to the debugging server.
|
||||
*
|
||||
|
|
|
@ -141,7 +141,7 @@ BrowserRootActor.prototype = {
|
|||
for (let name in aFactories) {
|
||||
let actor = this._extraActors[name];
|
||||
if (!actor) {
|
||||
actor = aFactories[name].bind(null, this.conn);
|
||||
actor = aFactories[name].bind(null, this.conn, this);
|
||||
actor.prototype = aFactories[name].prototype;
|
||||
actor.parentID = this.actorID;
|
||||
this._extraActors[name] = actor;
|
||||
|
|
|
@ -185,6 +185,9 @@ var DebuggerServer = {
|
|||
*/
|
||||
addBrowserActors: function DH_addBrowserActors() {
|
||||
this.addActors("chrome://global/content/devtools/dbg-browser-actors.js");
|
||||
this.addActors("chrome://global/content/devtools/dbg-webconsole-actors.js");
|
||||
this.addTabActor(this.WebConsoleActor, "consoleActor");
|
||||
this.addGlobalActor(this.WebConsoleActor, "consoleActor");
|
||||
if ("nsIProfiler" in Ci)
|
||||
this.addActors("chrome://global/content/devtools/dbg-profiler-actors.js");
|
||||
},
|
||||
|
@ -535,6 +538,7 @@ DebuggerServerConnection.prototype = {
|
|||
"': " + safeErrorString(e))
|
||||
});
|
||||
}
|
||||
instance.parentID = actor.parentID;
|
||||
// We want the newly-constructed actor to completely replace the factory
|
||||
// actor. Reusing the existing actor ID will make sure ActorPool.addActor
|
||||
// does the right thing.
|
||||
|
|
|
@ -7,4 +7,5 @@ toolkit.jar:
|
|||
content/global/devtools/dbg-server.js (debugger/server/dbg-server.js)
|
||||
content/global/devtools/dbg-script-actors.js (debugger/server/dbg-script-actors.js)
|
||||
content/global/devtools/dbg-browser-actors.js (debugger/server/dbg-browser-actors.js)
|
||||
content/global/devtools/dbg-webconsole-actors.js (webconsole/dbg-webconsole-actors.js)
|
||||
content/global/devtools/dbg-profiler-actors.js (debugger/server/dbg-profiler-actors.js)
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
DEPTH = ../../..
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
ifneq (Android,$(OS_TARGET))
|
||||
TEST_DIRS += test
|
||||
endif
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
libs::
|
||||
$(INSTALL) $(IFLAGS1) $(srcdir)/*.jsm $(FINAL_TARGET)/modules/devtools
|
|
@ -99,8 +99,6 @@ var NetworkHelper =
|
|||
return conv.ConvertToUnicode(aText);
|
||||
}
|
||||
catch (ex) {
|
||||
Cu.reportError("NH_convertToUnicode(aText, '" +
|
||||
aCharset + "') exception: " + ex);
|
||||
return aText;
|
||||
}
|
||||
},
|
||||
|
@ -177,8 +175,24 @@ var NetworkHelper =
|
|||
readPostTextFromPage: function NH_readPostTextFromPage(aDocShell, aCharset)
|
||||
{
|
||||
let webNav = aDocShell.QueryInterface(Ci.nsIWebNavigation);
|
||||
if (webNav instanceof Ci.nsIWebPageDescriptor) {
|
||||
let descriptor = webNav.currentDescriptor;
|
||||
return this.readPostTextFromPageViaWebNav(webNav, aCharset);
|
||||
},
|
||||
|
||||
/**
|
||||
* Reads the posted text from the page's cache, given an nsIWebNavigation
|
||||
* object.
|
||||
*
|
||||
* @param nsIWebNavigation aWebNav
|
||||
* @param string aCharset
|
||||
* @returns string or null
|
||||
* Returns the posted string if it was possible to read from
|
||||
* aWebNav, otherwise null.
|
||||
*/
|
||||
readPostTextFromPageViaWebNav:
|
||||
function NH_readPostTextFromPageViaWebNav(aWebNav, aCharset)
|
||||
{
|
||||
if (aWebNav instanceof Ci.nsIWebPageDescriptor) {
|
||||
let descriptor = aWebNav.currentDescriptor;
|
||||
|
||||
if (descriptor instanceof Ci.nsISHEntry && descriptor.postData &&
|
||||
descriptor instanceof Ci.nsISeekableStream) {
|
|
@ -0,0 +1,309 @@
|
|||
/* -*- Mode: js2; js2-basic-offset: 2; indent-tabs-mode: nil; -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
const Cu = Components.utils;
|
||||
|
||||
var EXPORTED_SYMBOLS = ["WebConsoleClient"];
|
||||
|
||||
/**
|
||||
* A WebConsoleClient is used as a front end for the WebConsoleActor that is
|
||||
* created on the server, hiding implementation details.
|
||||
*
|
||||
* @param object aDebuggerClient
|
||||
* The DebuggerClient instance we live for.
|
||||
* @param string aActor
|
||||
* The WebConsoleActor ID.
|
||||
*/
|
||||
function WebConsoleClient(aDebuggerClient, aActor)
|
||||
{
|
||||
this._actor = aActor;
|
||||
this._client = aDebuggerClient;
|
||||
}
|
||||
|
||||
WebConsoleClient.prototype = {
|
||||
/**
|
||||
* Retrieve the cached messages from the server.
|
||||
*
|
||||
* @see this.CACHED_MESSAGES
|
||||
* @param array aTypes
|
||||
* The array of message types you want from the server. See
|
||||
* this.CACHED_MESSAGES for known types.
|
||||
* @param function aOnResponse
|
||||
* The function invoked when the response is received.
|
||||
*/
|
||||
getCachedMessages: function WCC_getCachedMessages(aTypes, aOnResponse)
|
||||
{
|
||||
let packet = {
|
||||
to: this._actor,
|
||||
type: "getCachedMessages",
|
||||
messageTypes: aTypes,
|
||||
};
|
||||
this._client.request(packet, aOnResponse);
|
||||
},
|
||||
|
||||
/**
|
||||
* Inspect the properties of an object.
|
||||
*
|
||||
* @param string aActor
|
||||
* The WebConsoleObjectActor ID to send the request to.
|
||||
* @param function aOnResponse
|
||||
* The function invoked when the response is received.
|
||||
*/
|
||||
inspectObjectProperties:
|
||||
function WCC_inspectObjectProperties(aActor, aOnResponse)
|
||||
{
|
||||
let packet = {
|
||||
to: aActor,
|
||||
type: "inspectProperties",
|
||||
};
|
||||
this._client.request(packet, aOnResponse);
|
||||
},
|
||||
|
||||
/**
|
||||
* Evaluate a JavaScript expression.
|
||||
*
|
||||
* @param string aString
|
||||
* The code you want to evaluate.
|
||||
* @param function aOnResponse
|
||||
* The function invoked when the response is received.
|
||||
*/
|
||||
evaluateJS: function WCC_evaluateJS(aString, aOnResponse)
|
||||
{
|
||||
let packet = {
|
||||
to: this._actor,
|
||||
type: "evaluateJS",
|
||||
text: aString,
|
||||
};
|
||||
this._client.request(packet, aOnResponse);
|
||||
},
|
||||
|
||||
/**
|
||||
* Autocomplete a JavaScript expression.
|
||||
*
|
||||
* @param string aString
|
||||
* The code you want to autocomplete.
|
||||
* @param number aCursor
|
||||
* Cursor location inside the string. Index starts from 0.
|
||||
* @param function aOnResponse
|
||||
* The function invoked when the response is received.
|
||||
*/
|
||||
autocomplete: function WCC_autocomplete(aString, aCursor, aOnResponse)
|
||||
{
|
||||
let packet = {
|
||||
to: this._actor,
|
||||
type: "autocomplete",
|
||||
text: aString,
|
||||
cursor: aCursor,
|
||||
};
|
||||
this._client.request(packet, aOnResponse);
|
||||
},
|
||||
|
||||
/**
|
||||
* Clear the cache of messages (page errors and console API calls).
|
||||
*/
|
||||
clearMessagesCache: function WCC_clearMessagesCache()
|
||||
{
|
||||
let packet = {
|
||||
to: this._actor,
|
||||
type: "clearMessagesCache",
|
||||
};
|
||||
this._client.request(packet);
|
||||
},
|
||||
|
||||
/**
|
||||
* Set Web Console-related preferences on the server.
|
||||
*
|
||||
* @param object aPreferences
|
||||
* An object with the preferences you want to change.
|
||||
* @param function [aOnResponse]
|
||||
* Optional function to invoke when the response is received.
|
||||
*/
|
||||
setPreferences: function WCC_setPreferences(aPreferences, aOnResponse)
|
||||
{
|
||||
let packet = {
|
||||
to: this._actor,
|
||||
type: "setPreferences",
|
||||
preferences: aPreferences,
|
||||
};
|
||||
this._client.request(packet, aOnResponse);
|
||||
},
|
||||
|
||||
/**
|
||||
* Retrieve the request headers from the given NetworkEventActor.
|
||||
*
|
||||
* @param string aActor
|
||||
* The NetworkEventActor ID.
|
||||
* @param function aOnResponse
|
||||
* The function invoked when the response is received.
|
||||
*/
|
||||
getRequestHeaders: function WCC_getRequestHeaders(aActor, aOnResponse)
|
||||
{
|
||||
let packet = {
|
||||
to: aActor,
|
||||
type: "getRequestHeaders",
|
||||
};
|
||||
this._client.request(packet, aOnResponse);
|
||||
},
|
||||
|
||||
/**
|
||||
* Retrieve the request cookies from the given NetworkEventActor.
|
||||
*
|
||||
* @param string aActor
|
||||
* The NetworkEventActor ID.
|
||||
* @param function aOnResponse
|
||||
* The function invoked when the response is received.
|
||||
*/
|
||||
getRequestCookies: function WCC_getRequestCookies(aActor, aOnResponse)
|
||||
{
|
||||
let packet = {
|
||||
to: aActor,
|
||||
type: "getRequestCookies",
|
||||
};
|
||||
this._client.request(packet, aOnResponse);
|
||||
},
|
||||
|
||||
/**
|
||||
* Retrieve the request post data from the given NetworkEventActor.
|
||||
*
|
||||
* @param string aActor
|
||||
* The NetworkEventActor ID.
|
||||
* @param function aOnResponse
|
||||
* The function invoked when the response is received.
|
||||
*/
|
||||
getRequestPostData: function WCC_getRequestPostData(aActor, aOnResponse)
|
||||
{
|
||||
let packet = {
|
||||
to: aActor,
|
||||
type: "getRequestPostData",
|
||||
};
|
||||
this._client.request(packet, aOnResponse);
|
||||
},
|
||||
|
||||
/**
|
||||
* Retrieve the response headers from the given NetworkEventActor.
|
||||
*
|
||||
* @param string aActor
|
||||
* The NetworkEventActor ID.
|
||||
* @param function aOnResponse
|
||||
* The function invoked when the response is received.
|
||||
*/
|
||||
getResponseHeaders: function WCC_getResponseHeaders(aActor, aOnResponse)
|
||||
{
|
||||
let packet = {
|
||||
to: aActor,
|
||||
type: "getResponseHeaders",
|
||||
};
|
||||
this._client.request(packet, aOnResponse);
|
||||
},
|
||||
|
||||
/**
|
||||
* Retrieve the response cookies from the given NetworkEventActor.
|
||||
*
|
||||
* @param string aActor
|
||||
* The NetworkEventActor ID.
|
||||
* @param function aOnResponse
|
||||
* The function invoked when the response is received.
|
||||
*/
|
||||
getResponseCookies: function WCC_getResponseCookies(aActor, aOnResponse)
|
||||
{
|
||||
let packet = {
|
||||
to: aActor,
|
||||
type: "getResponseCookies",
|
||||
};
|
||||
this._client.request(packet, aOnResponse);
|
||||
},
|
||||
|
||||
/**
|
||||
* Retrieve the response content from the given NetworkEventActor.
|
||||
*
|
||||
* @param string aActor
|
||||
* The NetworkEventActor ID.
|
||||
* @param function aOnResponse
|
||||
* The function invoked when the response is received.
|
||||
*/
|
||||
getResponseContent: function WCC_getResponseContent(aActor, aOnResponse)
|
||||
{
|
||||
let packet = {
|
||||
to: aActor,
|
||||
type: "getResponseContent",
|
||||
};
|
||||
this._client.request(packet, aOnResponse);
|
||||
},
|
||||
|
||||
/**
|
||||
* Retrieve the timing information for the given NetworkEventActor.
|
||||
*
|
||||
* @param string aActor
|
||||
* The NetworkEventActor ID.
|
||||
* @param function aOnResponse
|
||||
* The function invoked when the response is received.
|
||||
*/
|
||||
getEventTimings: function WCC_getEventTimings(aActor, aOnResponse)
|
||||
{
|
||||
let packet = {
|
||||
to: aActor,
|
||||
type: "getEventTimings",
|
||||
};
|
||||
this._client.request(packet, aOnResponse);
|
||||
},
|
||||
|
||||
/**
|
||||
* Start the given Web Console listeners.
|
||||
*
|
||||
* @see this.LISTENERS
|
||||
* @param array aListeners
|
||||
* Array of listeners you want to start. See this.LISTENERS for
|
||||
* known listeners.
|
||||
* @param function aOnResponse
|
||||
* Function to invoke when the server response is received.
|
||||
*/
|
||||
startListeners: function WCC_startListeners(aListeners, aOnResponse)
|
||||
{
|
||||
let packet = {
|
||||
to: this._actor,
|
||||
type: "startListeners",
|
||||
listeners: aListeners,
|
||||
};
|
||||
this._client.request(packet, aOnResponse);
|
||||
},
|
||||
|
||||
/**
|
||||
* Stop the given Web Console listeners.
|
||||
*
|
||||
* @see this.LISTENERS
|
||||
* @param array aListeners
|
||||
* Array of listeners you want to stop. See this.LISTENERS for
|
||||
* known listeners.
|
||||
* @param function aOnResponse
|
||||
* Function to invoke when the server response is received.
|
||||
*/
|
||||
stopListeners: function WCC_stopListeners(aListeners, aOnResponse)
|
||||
{
|
||||
let packet = {
|
||||
to: this._actor,
|
||||
type: "stopListeners",
|
||||
listeners: aListeners,
|
||||
};
|
||||
this._client.request(packet, aOnResponse);
|
||||
},
|
||||
|
||||
/**
|
||||
* Close the WebConsoleClient. This stops all the listeners on the server and
|
||||
* detaches from the console actor.
|
||||
*
|
||||
* @param function aOnResponse
|
||||
* Function to invoke when the server response is received.
|
||||
*/
|
||||
close: function WCC_close(aOnResponse)
|
||||
{
|
||||
this.stopListeners(null, aOnResponse);
|
||||
this._client = null;
|
||||
},
|
||||
};
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -0,0 +1,27 @@
|
|||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
DEPTH = @DEPTH@
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
relativesrcdir = @relativesrcdir@
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
MOCHITEST_CHROME_FILES = \
|
||||
test_basics.html \
|
||||
test_cached_messages.html \
|
||||
test_page_errors.html \
|
||||
test_consoleapi.html \
|
||||
test_jsterm.html \
|
||||
test_object_actor.html \
|
||||
test_network_get.html \
|
||||
test_network_post.html \
|
||||
network_requests_iframe.html \
|
||||
data.json \
|
||||
common.js \
|
||||
$(NULL)
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
|
@ -0,0 +1,139 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
|
||||
|
||||
const XHTML_NS = "http://www.w3.org/1999/xhtml";
|
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/devtools/WebConsoleUtils.jsm");
|
||||
|
||||
function initCommon()
|
||||
{
|
||||
//Services.prefs.setBoolPref("devtools.debugger.log", true);
|
||||
|
||||
Cu.import("resource://gre/modules/devtools/dbg-server.jsm");
|
||||
Cu.import("resource://gre/modules/devtools/dbg-client.jsm");
|
||||
}
|
||||
|
||||
function initDebuggerServer()
|
||||
{
|
||||
if (!DebuggerServer.initialized) {
|
||||
DebuggerServer.init();
|
||||
DebuggerServer.addBrowserActors();
|
||||
}
|
||||
}
|
||||
|
||||
function connectToDebugger(aCallback)
|
||||
{
|
||||
initCommon();
|
||||
initDebuggerServer();
|
||||
|
||||
let transport = DebuggerServer.connectPipe();
|
||||
let client = new DebuggerClient(transport);
|
||||
|
||||
let dbgState = { dbgClient: client };
|
||||
client.connect(aCallback.bind(null, dbgState));
|
||||
}
|
||||
|
||||
function attachConsole(aListeners, aCallback, aAttachToTab)
|
||||
{
|
||||
function _onAttachConsole(aState, aResponse, aWebConsoleClient)
|
||||
{
|
||||
if (aResponse.error) {
|
||||
Cu.reportError("attachConsole failed: " + aResponse.error + " " +
|
||||
aResponse.message);
|
||||
}
|
||||
|
||||
aState.client = aWebConsoleClient;
|
||||
|
||||
aCallback(aState, aResponse);
|
||||
}
|
||||
|
||||
connectToDebugger(function _onConnect(aState, aResponse) {
|
||||
if (aResponse.error) {
|
||||
Cu.reportError("client.connect() failed: " + aResponse.error + " " +
|
||||
aResponse.message);
|
||||
aCallback(aState, aResponse);
|
||||
return;
|
||||
}
|
||||
|
||||
aState.dbgClient.listTabs(function _onListTabs(aResponse) {
|
||||
if (aResponse.error) {
|
||||
Cu.reportError("listTabs failed: " + aResponse.error + " " +
|
||||
aResponse.message);
|
||||
aCallback(aState, aResponse);
|
||||
return;
|
||||
}
|
||||
let consoleActor = aAttachToTab ?
|
||||
aResponse.tabs[aResponse.selected].consoleActor :
|
||||
aResponse.consoleActor;
|
||||
aState.actor = consoleActor;
|
||||
aState.dbgClient.attachConsole(consoleActor, aListeners,
|
||||
_onAttachConsole.bind(null, aState));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function closeDebugger(aState, aCallback)
|
||||
{
|
||||
aState.dbgClient.close(aCallback);
|
||||
aState.dbgClient = null;
|
||||
aState.client = null;
|
||||
}
|
||||
|
||||
function checkConsoleAPICall(aCall, aExpected)
|
||||
{
|
||||
if (aExpected.level != "trace" && aExpected.arguments) {
|
||||
is(aCall.arguments.length, aExpected.arguments.length,
|
||||
"number of arguments");
|
||||
}
|
||||
|
||||
checkObject(aCall, aExpected);
|
||||
}
|
||||
|
||||
function checkObject(aObject, aExpected)
|
||||
{
|
||||
for (let name of Object.keys(aExpected))
|
||||
{
|
||||
let expected = aExpected[name];
|
||||
let value = aObject[name];
|
||||
if (value === undefined) {
|
||||
ok(false, "'" + name + "' is undefined");
|
||||
}
|
||||
else if (typeof expected == "string" ||
|
||||
typeof expected == "number" ||
|
||||
typeof expected == "boolean") {
|
||||
is(value, expected, "property '" + name + "'");
|
||||
}
|
||||
else if (expected instanceof RegExp) {
|
||||
ok(expected.test(value), name + ": " + expected);
|
||||
}
|
||||
else if (Array.isArray(expected)) {
|
||||
info("checking array for property '" + name + "'");
|
||||
checkObject(value, expected);
|
||||
}
|
||||
else if (typeof expected == "object") {
|
||||
info("checking object for property '" + name + "'");
|
||||
checkObject(value, expected);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function checkHeadersOrCookies(aArray, aExpected)
|
||||
{
|
||||
for (let elem of aArray) {
|
||||
if (!(elem.name in aExpected)) {
|
||||
continue;
|
||||
}
|
||||
let expected = aExpected[elem.name];
|
||||
if (expected instanceof RegExp) {
|
||||
ok(expected.test(elem.value), elem.name + ": " + expected);
|
||||
}
|
||||
else {
|
||||
is(elem.value, expected, elem.name);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
{ id: "test JSON data", myArray: [ "foo", "bar", "baz", "biff" ] }
|
|
@ -0,0 +1,43 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Console HTTP test page</title>
|
||||
<!-- Any copyright is dedicated to the Public Domain.
|
||||
- http://creativecommons.org/publicdomain/zero/1.0/ -->
|
||||
<script type="text/javascript"><!--
|
||||
function makeXhr(aMethod, aUrl, aRequestBody, aCallback) {
|
||||
var xmlhttp = new XMLHttpRequest();
|
||||
xmlhttp.open(aMethod, aUrl, true);
|
||||
if (aCallback) {
|
||||
xmlhttp.onreadystatechange = function() {
|
||||
if (xmlhttp.readyState == 4) {
|
||||
aCallback();
|
||||
}
|
||||
};
|
||||
}
|
||||
xmlhttp.send(aRequestBody);
|
||||
}
|
||||
|
||||
function testXhrGet(aCallback) {
|
||||
makeXhr('get', 'data.json', null, aCallback);
|
||||
}
|
||||
|
||||
function testXhrPost(aCallback) {
|
||||
makeXhr('post', 'data.json', "Hello world!", aCallback);
|
||||
}
|
||||
|
||||
document.cookie = "foobar=fooval";
|
||||
document.cookie = "omgfoo=bug768096";
|
||||
// --></script>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Web Console HTTP Logging Testpage</h1>
|
||||
<h2>This page is used to test the HTTP logging.</h2>
|
||||
|
||||
<form action="?" method="post">
|
||||
<input name="name" type="text" value="foo bar"><br>
|
||||
<input name="age" type="text" value="144"><br>
|
||||
</form>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,79 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf8">
|
||||
<title>Basic Web Console Actor tests</title>
|
||||
<script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript;version=1.8" src="common.js"></script>
|
||||
<!-- Any copyright is dedicated to the Public Domain.
|
||||
- http://creativecommons.org/publicdomain/zero/1.0/ -->
|
||||
</head>
|
||||
<body>
|
||||
<p>Basic Web Console Actor tests</p>
|
||||
|
||||
<script class="testbody" type="text/javascript;version=1.8">
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
function startTest()
|
||||
{
|
||||
removeEventListener("load", startTest);
|
||||
|
||||
attachConsole(["PageError"], onStartPageError);
|
||||
}
|
||||
|
||||
function onStartPageError(aState, aResponse)
|
||||
{
|
||||
is(aResponse.startedListeners.length, 1, "startedListeners.length");
|
||||
is(aResponse.startedListeners[0], "PageError", "startedListeners: PageError");
|
||||
ok(aResponse.nativeConsoleAPI, "nativeConsoleAPI");
|
||||
|
||||
closeDebugger(aState, function() {
|
||||
top.console_ = top.console;
|
||||
top.console = { lolz: "foo" };
|
||||
attachConsole(["PageError", "ConsoleAPI", "foo"],
|
||||
onStartPageErrorAndConsoleAPI, true);
|
||||
});
|
||||
}
|
||||
|
||||
function onStartPageErrorAndConsoleAPI(aState, aResponse)
|
||||
{
|
||||
let startedListeners = aResponse.startedListeners;
|
||||
is(startedListeners.length, 2, "startedListeners.length");
|
||||
isnot(startedListeners.indexOf("PageError"), -1, "startedListeners: PageError");
|
||||
isnot(startedListeners.indexOf("ConsoleAPI"), -1,
|
||||
"startedListeners: ConsoleAPI");
|
||||
is(startedListeners.indexOf("foo"), -1, "startedListeners: no foo");
|
||||
ok(!aResponse.nativeConsoleAPI, "!nativeConsoleAPI");
|
||||
|
||||
aState.client.stopListeners(["ConsoleAPI", "foo"],
|
||||
onStopConsoleAPI.bind(null, aState));
|
||||
}
|
||||
|
||||
function onStopConsoleAPI(aState, aResponse)
|
||||
{
|
||||
is(aResponse.stoppedListeners.length, 1, "stoppedListeners.length");
|
||||
is(aResponse.stoppedListeners[0], "ConsoleAPI", "stoppedListeners: ConsoleAPI");
|
||||
|
||||
closeDebugger(aState, function() {
|
||||
attachConsole(["ConsoleAPI"], onStartConsoleAPI);
|
||||
});
|
||||
}
|
||||
|
||||
function onStartConsoleAPI(aState, aResponse)
|
||||
{
|
||||
is(aResponse.startedListeners.length, 1, "startedListeners.length");
|
||||
is(aResponse.startedListeners[0], "ConsoleAPI", "startedListeners: ConsoleAPI");
|
||||
ok(aResponse.nativeConsoleAPI, "nativeConsoleAPI");
|
||||
|
||||
top.console = top.console_;
|
||||
delete top.console_;
|
||||
|
||||
closeDebugger(aState, function() {
|
||||
SimpleTest.finish();
|
||||
});
|
||||
}
|
||||
|
||||
addEventListener("load", startTest);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,179 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf8">
|
||||
<title>Test for cached messages</title>
|
||||
<script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript;version=1.8" src="common.js"></script>
|
||||
<!-- Any copyright is dedicated to the Public Domain.
|
||||
- http://creativecommons.org/publicdomain/zero/1.0/ -->
|
||||
</head>
|
||||
<body>
|
||||
<p>Test for cached messages</p>
|
||||
|
||||
<script class="testbody" type="application/javascript;version=1.8">
|
||||
let expectedConsoleCalls = [];
|
||||
let expectedPageErrors = [];
|
||||
|
||||
(function() {
|
||||
Services.console.reset();
|
||||
|
||||
expectedPageErrors = [
|
||||
{
|
||||
_type: "PageError",
|
||||
errorMessage: /fooColor/,
|
||||
sourceName: /.+/,
|
||||
category: "CSS Parser",
|
||||
timeStamp: /^\d+$/,
|
||||
error: false,
|
||||
warning: true,
|
||||
exception: false,
|
||||
strict: false,
|
||||
},
|
||||
{
|
||||
_type: "PageError",
|
||||
errorMessage: /doTheImpossible/,
|
||||
sourceName: /.+/,
|
||||
category: "chrome javascript",
|
||||
timeStamp: /^\d+$/,
|
||||
error: false,
|
||||
warning: false,
|
||||
exception: true,
|
||||
strict: false,
|
||||
},
|
||||
];
|
||||
|
||||
let body = top.document.documentElement;
|
||||
let container = top.document.createElementNS(XHTML_NS, "script");
|
||||
body.appendChild(container);
|
||||
container.textContent = "document.documentElement.style.color = 'fooColor';";
|
||||
body.removeChild(container);
|
||||
|
||||
container = top.document.createElementNS(XHTML_NS, "script");
|
||||
body.appendChild(container);
|
||||
container.textContent = "document.doTheImpossible();";
|
||||
body.removeChild(container);
|
||||
})();
|
||||
|
||||
function doConsoleCalls()
|
||||
{
|
||||
top.console.log("foobarBaz-log", undefined);
|
||||
top.console.info("foobarBaz-info", null);
|
||||
top.console.warn("foobarBaz-warn", document.body);
|
||||
|
||||
expectedConsoleCalls = [
|
||||
{
|
||||
_type: "ConsoleAPI",
|
||||
level: "log",
|
||||
filename: /test_cached_messages/,
|
||||
functionName: "doConsoleCalls",
|
||||
timeStamp: /^\d+$/,
|
||||
arguments: ["foobarBaz-log", { type: "undefined" }],
|
||||
},
|
||||
{
|
||||
_type: "ConsoleAPI",
|
||||
level: "info",
|
||||
filename: /test_cached_messages/,
|
||||
functionName: "doConsoleCalls",
|
||||
timeStamp: /^\d+$/,
|
||||
arguments: ["foobarBaz-info", { type: "null" }],
|
||||
},
|
||||
{
|
||||
_type: "ConsoleAPI",
|
||||
level: "warn",
|
||||
filename: /test_cached_messages/,
|
||||
functionName: "doConsoleCalls",
|
||||
timeStamp: /^\d+$/,
|
||||
arguments: ["foobarBaz-warn", { type: "object", actor: /[a-z]/ }],
|
||||
},
|
||||
];
|
||||
}
|
||||
</script>
|
||||
|
||||
<script class="testbody" type="text/javascript;version=1.8">
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
let consoleAPIListener;
|
||||
|
||||
let consoleAPICalls = 0;
|
||||
|
||||
let handlers = {
|
||||
onConsoleAPICall: function onConsoleAPICall()
|
||||
{
|
||||
consoleAPICalls++;
|
||||
if (consoleAPICalls == expectedConsoleCalls.length) {
|
||||
checkConsoleAPICache();
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
function startTest()
|
||||
{
|
||||
removeEventListener("load", startTest);
|
||||
|
||||
consoleAPIListener = new ConsoleAPIListener(top, handlers);
|
||||
consoleAPIListener.init();
|
||||
|
||||
doConsoleCalls();
|
||||
}
|
||||
|
||||
function checkConsoleAPICache()
|
||||
{
|
||||
consoleAPIListener.destroy();
|
||||
consoleAPIListener = null;
|
||||
attachConsole(["ConsoleAPI"], onAttach1);
|
||||
}
|
||||
|
||||
function onAttach1(aState, aResponse)
|
||||
{
|
||||
aState.client.getCachedMessages(["ConsoleAPI"],
|
||||
onCachedConsoleAPI.bind(null, aState));
|
||||
}
|
||||
|
||||
function onCachedConsoleAPI(aState, aResponse)
|
||||
{
|
||||
let msgs = aResponse.messages;
|
||||
|
||||
is(msgs.length, expectedConsoleCalls.length,
|
||||
"number of cached console messages");
|
||||
|
||||
expectedConsoleCalls.forEach(function(aMessage, aIndex) {
|
||||
info("checking received cached message #" + aIndex);
|
||||
checkConsoleAPICall(msgs[aIndex], expectedConsoleCalls[aIndex]);
|
||||
});
|
||||
|
||||
closeDebugger(aState, testPageErrors);
|
||||
}
|
||||
|
||||
function testPageErrors()
|
||||
{
|
||||
attachConsole(["PageError"], onAttach2);
|
||||
}
|
||||
|
||||
function onAttach2(aState, aResponse)
|
||||
{
|
||||
aState.client.getCachedMessages(["PageError"],
|
||||
onCachedPageErrors.bind(null, aState));
|
||||
}
|
||||
|
||||
function onCachedPageErrors(aState, aResponse)
|
||||
{
|
||||
let msgs = aResponse.messages;
|
||||
|
||||
is(msgs.length, expectedPageErrors.length,
|
||||
"number of cached page errors");
|
||||
|
||||
expectedPageErrors.forEach(function(aMessage, aIndex) {
|
||||
info("checking received cached message #" + aIndex);
|
||||
checkObject(msgs[aIndex], expectedPageErrors[aIndex]);
|
||||
});
|
||||
|
||||
closeDebugger(aState, function() {
|
||||
SimpleTest.finish();
|
||||
});
|
||||
}
|
||||
|
||||
addEventListener("load", startTest);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,148 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf8">
|
||||
<title>Test for the Console API</title>
|
||||
<script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript;version=1.8" src="common.js"></script>
|
||||
<!-- Any copyright is dedicated to the Public Domain.
|
||||
- http://creativecommons.org/publicdomain/zero/1.0/ -->
|
||||
</head>
|
||||
<body>
|
||||
<p>Test for the Console API</p>
|
||||
|
||||
<script class="testbody" type="text/javascript;version=1.8">
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
let expectedConsoleCalls = [];
|
||||
|
||||
function doConsoleCalls(aState)
|
||||
{
|
||||
console.log("foobarBaz-log", undefined);
|
||||
console.info("foobarBaz-info", null);
|
||||
console.warn("foobarBaz-warn", document.body);
|
||||
console.debug(null);
|
||||
console.trace();
|
||||
console.dir(document, window);
|
||||
|
||||
expectedConsoleCalls = [
|
||||
{
|
||||
level: "log",
|
||||
filename: /test_consoleapi/,
|
||||
functionName: "doConsoleCalls",
|
||||
timeStamp: /^\d+$/,
|
||||
arguments: ["foobarBaz-log", { type: "undefined" }],
|
||||
},
|
||||
{
|
||||
level: "info",
|
||||
filename: /test_consoleapi/,
|
||||
functionName: "doConsoleCalls",
|
||||
timeStamp: /^\d+$/,
|
||||
arguments: ["foobarBaz-info", { type: "null" }],
|
||||
},
|
||||
{
|
||||
level: "warn",
|
||||
filename: /test_consoleapi/,
|
||||
functionName: "doConsoleCalls",
|
||||
timeStamp: /^\d+$/,
|
||||
arguments: ["foobarBaz-warn", { type: "object", actor: /[a-z]/ }],
|
||||
},
|
||||
{
|
||||
level: "debug",
|
||||
filename: /test_consoleapi/,
|
||||
functionName: "doConsoleCalls",
|
||||
timeStamp: /^\d+$/,
|
||||
arguments: [{ type: "null" }],
|
||||
},
|
||||
{
|
||||
level: "trace",
|
||||
filename: /test_consoleapi/,
|
||||
functionName: "doConsoleCalls",
|
||||
timeStamp: /^\d+$/,
|
||||
arguments: [
|
||||
{
|
||||
filename: /test_consoleapi/,
|
||||
functionName: "doConsoleCalls",
|
||||
},
|
||||
{
|
||||
filename: /test_consoleapi/,
|
||||
functionName: "onAttach",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
level: "dir",
|
||||
filename: /test_consoleapi/,
|
||||
functionName: "doConsoleCalls",
|
||||
timeStamp: /^\d+$/,
|
||||
arguments: [
|
||||
{
|
||||
type: "object",
|
||||
actor: /[a-z]/,
|
||||
className: "HTMLDocument",
|
||||
},
|
||||
{
|
||||
type: "object",
|
||||
actor: /[a-z]/,
|
||||
className: "Window",
|
||||
}
|
||||
],
|
||||
objectProperties: [
|
||||
{
|
||||
name: "ATTRIBUTE_NODE",
|
||||
value: 2,
|
||||
},
|
||||
{
|
||||
name: "CDATA_SECTION_NODE",
|
||||
value: 4,
|
||||
}, // ...
|
||||
],
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
function startTest()
|
||||
{
|
||||
removeEventListener("load", startTest);
|
||||
|
||||
attachConsole(["ConsoleAPI"], onAttach);
|
||||
}
|
||||
|
||||
function onAttach(aState, aResponse)
|
||||
{
|
||||
onConsoleAPICall = onConsoleAPICall.bind(null, aState);
|
||||
aState.dbgClient.addListener("consoleAPICall", onConsoleAPICall);
|
||||
doConsoleCalls(aState.actor);
|
||||
}
|
||||
|
||||
let consoleCalls = [];
|
||||
|
||||
function onConsoleAPICall(aState, aType, aPacket)
|
||||
{
|
||||
info("received message level: " + aPacket.message.level);
|
||||
is(aPacket.from, aState.actor, "console API call actor");
|
||||
|
||||
consoleCalls.push(aPacket.message);
|
||||
if (consoleCalls.length != expectedConsoleCalls.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
aState.dbgClient.removeListener("consoleAPICall", onConsoleAPICall);
|
||||
|
||||
expectedConsoleCalls.forEach(function(aMessage, aIndex) {
|
||||
info("checking received console call #" + aIndex);
|
||||
checkConsoleAPICall(consoleCalls[aIndex], expectedConsoleCalls[aIndex]);
|
||||
});
|
||||
|
||||
|
||||
consoleCalls = [];
|
||||
|
||||
closeDebugger(aState, function() {
|
||||
SimpleTest.finish();
|
||||
});
|
||||
}
|
||||
|
||||
addEventListener("load", startTest);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,145 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf8">
|
||||
<title>Test for JavaScript terminal functionality</title>
|
||||
<script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript;version=1.8" src="common.js"></script>
|
||||
<!-- Any copyright is dedicated to the Public Domain.
|
||||
- http://creativecommons.org/publicdomain/zero/1.0/ -->
|
||||
</head>
|
||||
<body>
|
||||
<p>Test for JavaScript terminal functionality</p>
|
||||
|
||||
<script class="testbody" type="text/javascript;version=1.8">
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
function startTest()
|
||||
{
|
||||
removeEventListener("load", startTest);
|
||||
|
||||
attachConsole(["PageError"], onAttach, true);
|
||||
}
|
||||
|
||||
function onAttach(aState, aResponse)
|
||||
{
|
||||
top.foobarObject = Object.create(null);
|
||||
top.foobarObject.foo = 1;
|
||||
top.foobarObject.foobar = 2;
|
||||
top.foobarObject.foobaz = 3;
|
||||
top.foobarObject.omg = 4;
|
||||
top.foobarObject.omgfoo = 5;
|
||||
|
||||
info("test autocomplete for 'window.foo'");
|
||||
onAutocomplete1 = onAutocomplete1.bind(null, aState);
|
||||
aState.client.autocomplete("window.foo", 0, onAutocomplete1);
|
||||
}
|
||||
|
||||
function onAutocomplete1(aState, aResponse)
|
||||
{
|
||||
let matches = aResponse.matches;
|
||||
|
||||
is(aResponse.matchProp, "foo", "matchProp");
|
||||
is(matches.length, 1, "matches.length");
|
||||
is(matches[0], "foobarObject", "matches[0]");
|
||||
|
||||
info("test autocomplete for 'window.foobarObject.'");
|
||||
|
||||
onAutocomplete2 = onAutocomplete2.bind(null, aState);
|
||||
aState.client.autocomplete("window.foobarObject.", 0, onAutocomplete2);
|
||||
}
|
||||
|
||||
function onAutocomplete2(aState, aResponse)
|
||||
{
|
||||
let matches = aResponse.matches;
|
||||
|
||||
ok(!aResponse.matchProp, "matchProp");
|
||||
is(matches.length, 5, "matches.length");
|
||||
checkObject(matches, ["foo", "foobar", "foobaz", "omg", "omgfoo"]);
|
||||
|
||||
info("test eval '2+2'");
|
||||
|
||||
onEval1 = onEval1.bind(null, aState);
|
||||
aState.client.evaluateJS("2+2", onEval1);
|
||||
}
|
||||
|
||||
function onEval1(aState, aResponse)
|
||||
{
|
||||
checkObject(aResponse, {
|
||||
from: aState.actor,
|
||||
input: "2+2",
|
||||
result: 4,
|
||||
});
|
||||
|
||||
ok(!aResponse.error, "no js error");
|
||||
ok(!aResponse.helperResult, "no helper result");
|
||||
|
||||
info("test eval 'window'");
|
||||
onEval2 = onEval2.bind(null, aState);
|
||||
aState.client.evaluateJS("window", onEval2);
|
||||
}
|
||||
|
||||
function onEval2(aState, aResponse)
|
||||
{
|
||||
checkObject(aResponse, {
|
||||
from: aState.actor,
|
||||
input: "window",
|
||||
result: {
|
||||
type: "object",
|
||||
className: "Window",
|
||||
actor: /[a-z]/,
|
||||
},
|
||||
});
|
||||
|
||||
ok(!aResponse.error, "no js error");
|
||||
ok(!aResponse.helperResult, "no helper result");
|
||||
|
||||
info("test eval with exception");
|
||||
|
||||
onEvalWithException = onEvalWithException.bind(null, aState);
|
||||
aState.client.evaluateJS("window.doTheImpossible()",
|
||||
onEvalWithException);
|
||||
}
|
||||
|
||||
function onEvalWithException(aState, aResponse)
|
||||
{
|
||||
checkObject(aResponse, {
|
||||
from: aState.actor,
|
||||
input: "window.doTheImpossible()",
|
||||
result: {
|
||||
type: "undefined",
|
||||
},
|
||||
errorMessage: /doTheImpossible/,
|
||||
});
|
||||
|
||||
ok(aResponse.error, "js error object");
|
||||
ok(!aResponse.helperResult, "no helper result");
|
||||
|
||||
info("test eval with helper");
|
||||
|
||||
onEvalWithHelper = onEvalWithHelper.bind(null, aState);
|
||||
aState.client.evaluateJS("clear()", onEvalWithHelper);
|
||||
}
|
||||
|
||||
function onEvalWithHelper(aState, aResponse)
|
||||
{
|
||||
checkObject(aResponse, {
|
||||
from: aState.actor,
|
||||
input: "clear()",
|
||||
result: {
|
||||
type: "undefined",
|
||||
},
|
||||
helperResult: { type: "clearOutput" },
|
||||
});
|
||||
|
||||
ok(!aResponse.error, "no js error");
|
||||
|
||||
closeDebugger(aState, function() {
|
||||
SimpleTest.finish();
|
||||
});
|
||||
}
|
||||
|
||||
addEventListener("load", startTest);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,242 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf8">
|
||||
<title>Test for the network actor (GET request)</title>
|
||||
<script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript;version=1.8" src="common.js"></script>
|
||||
<!-- Any copyright is dedicated to the Public Domain.
|
||||
- http://creativecommons.org/publicdomain/zero/1.0/ -->
|
||||
</head>
|
||||
<body>
|
||||
<p>Test for the network actor (GET request)</p>
|
||||
|
||||
<iframe src="http://example.com/chrome/toolkit/devtools/webconsole/test/network_requests_iframe.html"></iframe>
|
||||
|
||||
<script class="testbody" type="text/javascript;version=1.8">
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
function startTest()
|
||||
{
|
||||
removeEventListener("load", startTest);
|
||||
attachConsole(["NetworkActivity"], onAttach, true);
|
||||
}
|
||||
|
||||
function onAttach(aState, aResponse)
|
||||
{
|
||||
info("test network GET request");
|
||||
|
||||
onNetworkEvent = onNetworkEvent.bind(null, aState);
|
||||
aState.dbgClient.addListener("networkEvent", onNetworkEvent);
|
||||
onNetworkEventUpdate = onNetworkEventUpdate.bind(null, aState);
|
||||
aState.dbgClient.addListener("networkEventUpdate", onNetworkEventUpdate);
|
||||
|
||||
let iframe = document.querySelector("iframe").contentWindow;
|
||||
iframe.wrappedJSObject.testXhrGet();
|
||||
}
|
||||
|
||||
function onNetworkEvent(aState, aType, aPacket)
|
||||
{
|
||||
is(aPacket.from, aState.actor, "network event actor");
|
||||
|
||||
info("checking the network event packet");
|
||||
|
||||
let netActor = aPacket.eventActor;
|
||||
|
||||
checkObject(netActor, {
|
||||
actor: /[a-z]/,
|
||||
startedDateTime: /^\d+\-\d+\-\d+T.+$/,
|
||||
url: /data\.json/,
|
||||
method: "GET",
|
||||
});
|
||||
|
||||
aState.netActor = netActor.actor;
|
||||
|
||||
aState.dbgClient.removeListener("networkEvent", onNetworkEvent);
|
||||
}
|
||||
|
||||
let updates = [];
|
||||
|
||||
function onNetworkEventUpdate(aState, aType, aPacket)
|
||||
{
|
||||
info("received networkEventUpdate " + aPacket.updateType);
|
||||
is(aPacket.from, aState.netActor, "networkEventUpdate actor");
|
||||
|
||||
updates.push(aPacket.updateType);
|
||||
|
||||
let expectedPacket = null;
|
||||
|
||||
switch (aPacket.updateType) {
|
||||
case "requestHeaders":
|
||||
case "responseHeaders":
|
||||
ok(aPacket.headers > 0, "headers > 0");
|
||||
ok(aPacket.headersSize > 0, "headersSize > 0");
|
||||
break;
|
||||
case "requestCookies":
|
||||
expectedPacket = {
|
||||
cookies: 2,
|
||||
};
|
||||
break;
|
||||
case "requestPostData":
|
||||
ok(false, "got unexpected requestPostData");
|
||||
break;
|
||||
case "responseStart":
|
||||
expectedPacket = {
|
||||
response: {
|
||||
httpVersion: /^HTTP\/\d\.\d$/,
|
||||
status: 200,
|
||||
statusText: "OK",
|
||||
headersSize: /^\d+$/,
|
||||
discardResponseBody: true,
|
||||
},
|
||||
};
|
||||
break;
|
||||
case "responseCookies":
|
||||
expectedPacket = {
|
||||
cookies: 0,
|
||||
};
|
||||
break;
|
||||
case "responseContent":
|
||||
expectedPacket = {
|
||||
mimeType: /^application\/(json|octet-stream)$/,
|
||||
contentSize: 0,
|
||||
discardResponseBody: true,
|
||||
};
|
||||
break;
|
||||
case "eventTimings":
|
||||
expectedPacket = {
|
||||
totalTime: /^\d+$/,
|
||||
};
|
||||
break;
|
||||
default:
|
||||
ok(false, "unknown network event update type: " +
|
||||
aPacket.updateType);
|
||||
return;
|
||||
}
|
||||
|
||||
if (expectedPacket) {
|
||||
info("checking the packet content");
|
||||
checkObject(aPacket, expectedPacket);
|
||||
}
|
||||
|
||||
if (updates.indexOf("responseContent") > -1 &&
|
||||
updates.indexOf("eventTimings") > -1) {
|
||||
aState.dbgClient.removeListener("networkEventUpdate",
|
||||
onNetworkEvent);
|
||||
|
||||
onRequestHeaders = onRequestHeaders.bind(null, aState);
|
||||
aState.client.getRequestHeaders(aState.netActor,
|
||||
onRequestHeaders);
|
||||
}
|
||||
}
|
||||
|
||||
function onRequestHeaders(aState, aResponse)
|
||||
{
|
||||
info("checking request headers");
|
||||
|
||||
ok(aResponse.headers.length > 0, "request headers > 0");
|
||||
ok(aResponse.headersSize > 0, "request headersSize > 0");
|
||||
|
||||
checkHeadersOrCookies(aResponse.headers, {
|
||||
Referer: /network_requests_iframe\.html/,
|
||||
Cookie: /bug768096/,
|
||||
});
|
||||
|
||||
onRequestCookies = onRequestCookies.bind(null, aState);
|
||||
aState.client.getRequestCookies(aState.netActor,
|
||||
onRequestCookies);
|
||||
}
|
||||
|
||||
function onRequestCookies(aState, aResponse)
|
||||
{
|
||||
info("checking request cookies");
|
||||
|
||||
is(aResponse.cookies.length, 2, "request cookies length");
|
||||
|
||||
checkHeadersOrCookies(aResponse.cookies, {
|
||||
foobar: "fooval",
|
||||
omgfoo: "bug768096",
|
||||
});
|
||||
|
||||
onRequestPostData = onRequestPostData.bind(null, aState);
|
||||
aState.client.getRequestPostData(aState.netActor,
|
||||
onRequestPostData);
|
||||
}
|
||||
|
||||
function onRequestPostData(aState, aResponse)
|
||||
{
|
||||
info("checking request POST data");
|
||||
|
||||
ok(!aResponse.postData.text, "no request POST data");
|
||||
ok(aResponse.postDataDiscarded, "request POST data was discarded");
|
||||
|
||||
onResponseHeaders = onResponseHeaders.bind(null, aState);
|
||||
aState.client.getResponseHeaders(aState.netActor,
|
||||
onResponseHeaders);
|
||||
}
|
||||
|
||||
function onResponseHeaders(aState, aResponse)
|
||||
{
|
||||
info("checking response headers");
|
||||
|
||||
ok(aResponse.headers.length > 0, "response headers > 0");
|
||||
ok(aResponse.headersSize > 0, "response headersSize > 0");
|
||||
|
||||
checkHeadersOrCookies(aResponse.headers, {
|
||||
"Content-Type": /^application\/(json|octet-stream)$/,
|
||||
"Content-Length": /^\d+$/,
|
||||
});
|
||||
|
||||
onResponseCookies = onResponseCookies.bind(null, aState);
|
||||
aState.client.getResponseCookies(aState.netActor,
|
||||
onResponseCookies);
|
||||
}
|
||||
|
||||
function onResponseCookies(aState, aResponse)
|
||||
{
|
||||
info("checking response cookies");
|
||||
|
||||
is(aResponse.cookies.length, 0, "response cookies length");
|
||||
|
||||
onResponseContent = onResponseContent.bind(null, aState);
|
||||
aState.client.getResponseContent(aState.netActor,
|
||||
onResponseContent);
|
||||
}
|
||||
|
||||
function onResponseContent(aState, aResponse)
|
||||
{
|
||||
info("checking response content");
|
||||
|
||||
ok(!aResponse.content.text, "no response content");
|
||||
ok(aResponse.contentDiscarded, "response content was discarded");
|
||||
|
||||
onEventTimings = onEventTimings.bind(null, aState);
|
||||
aState.client.getEventTimings(aState.netActor,
|
||||
onEventTimings);
|
||||
}
|
||||
|
||||
function onEventTimings(aState, aResponse)
|
||||
{
|
||||
info("checking event timings");
|
||||
|
||||
checkObject(aResponse, {
|
||||
timings: {
|
||||
blocked: /^-1|\d+$/,
|
||||
dns: /^-1|\d+$/,
|
||||
connect: /^-1|\d+$/,
|
||||
send: /^-1|\d+$/,
|
||||
wait: /^-1|\d+$/,
|
||||
receive: /^-1|\d+$/,
|
||||
},
|
||||
totalTime: /^\d+$/,
|
||||
});
|
||||
|
||||
closeDebugger(aState, function() {
|
||||
SimpleTest.finish();
|
||||
});
|
||||
}
|
||||
|
||||
addEventListener("load", startTest);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,266 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf8">
|
||||
<title>Test for the network actor (POST request)</title>
|
||||
<script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript;version=1.8" src="common.js"></script>
|
||||
<!-- Any copyright is dedicated to the Public Domain.
|
||||
- http://creativecommons.org/publicdomain/zero/1.0/ -->
|
||||
</head>
|
||||
<body>
|
||||
<p>Test for the network actor (POST request)</p>
|
||||
|
||||
<iframe src="http://example.com/chrome/toolkit/devtools/webconsole/test/network_requests_iframe.html"></iframe>
|
||||
|
||||
<script class="testbody" type="text/javascript;version=1.8">
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
function startTest()
|
||||
{
|
||||
removeEventListener("load", startTest);
|
||||
|
||||
attachConsole(["NetworkActivity"], onAttach, true);
|
||||
}
|
||||
|
||||
function onAttach(aState, aResponse)
|
||||
{
|
||||
info("enable network request and response body logging");
|
||||
|
||||
onSetPreferences = onSetPreferences.bind(null, aState);
|
||||
aState.client.setPreferences({
|
||||
"NetworkMonitor.saveRequestAndResponseBodies": true,
|
||||
}, onSetPreferences);
|
||||
}
|
||||
|
||||
function onSetPreferences(aState, aResponse)
|
||||
{
|
||||
is(aResponse.updated.length, 1, "updated prefs length");
|
||||
is(aResponse.updated[0], "NetworkMonitor.saveRequestAndResponseBodies",
|
||||
"updated prefs length");
|
||||
|
||||
info("test network POST request");
|
||||
|
||||
onNetworkEvent = onNetworkEvent.bind(null, aState);
|
||||
aState.dbgClient.addListener("networkEvent", onNetworkEvent);
|
||||
onNetworkEventUpdate = onNetworkEventUpdate.bind(null, aState);
|
||||
aState.dbgClient.addListener("networkEventUpdate", onNetworkEventUpdate);
|
||||
|
||||
let iframe = document.querySelector("iframe").contentWindow;
|
||||
iframe.wrappedJSObject.testXhrPost();
|
||||
}
|
||||
|
||||
function onNetworkEvent(aState, aType, aPacket)
|
||||
{
|
||||
is(aPacket.from, aState.actor, "network event actor");
|
||||
|
||||
info("checking the network event packet");
|
||||
|
||||
let netActor = aPacket.eventActor;
|
||||
|
||||
checkObject(netActor, {
|
||||
actor: /[a-z]/,
|
||||
startedDateTime: /^\d+\-\d+\-\d+T.+$/,
|
||||
url: /data\.json/,
|
||||
method: "POST",
|
||||
});
|
||||
|
||||
aState.netActor = netActor.actor;
|
||||
|
||||
aState.dbgClient.removeListener("networkEvent", onNetworkEvent);
|
||||
}
|
||||
|
||||
let updates = [];
|
||||
|
||||
function onNetworkEventUpdate(aState, aType, aPacket)
|
||||
{
|
||||
info("received networkEventUpdate " + aPacket.updateType);
|
||||
is(aPacket.from, aState.netActor, "networkEventUpdate actor");
|
||||
|
||||
updates.push(aPacket.updateType);
|
||||
|
||||
let expectedPacket = null;
|
||||
|
||||
switch (aPacket.updateType) {
|
||||
case "requestHeaders":
|
||||
case "responseHeaders":
|
||||
ok(aPacket.headers > 0, "headers > 0");
|
||||
ok(aPacket.headersSize > 0, "headersSize > 0");
|
||||
break;
|
||||
case "requestCookies":
|
||||
expectedPacket = {
|
||||
cookies: 2,
|
||||
};
|
||||
break;
|
||||
case "requestPostData":
|
||||
ok(aPacket.dataSize > 0, "dataSize > 0");
|
||||
ok(!aPacket.discardRequestBody, "discardRequestBody");
|
||||
break;
|
||||
case "responseStart":
|
||||
expectedPacket = {
|
||||
response: {
|
||||
httpVersion: /^HTTP\/\d\.\d$/,
|
||||
status: 200,
|
||||
statusText: "OK",
|
||||
headersSize: /^\d+$/,
|
||||
discardResponseBody: false,
|
||||
},
|
||||
};
|
||||
break;
|
||||
case "responseCookies":
|
||||
expectedPacket = {
|
||||
cookies: 0,
|
||||
};
|
||||
break;
|
||||
case "responseContent":
|
||||
expectedPacket = {
|
||||
mimeType: /^application\/(json|octet-stream)$/,
|
||||
contentSize: /^\d+$/,
|
||||
discardResponseBody: false,
|
||||
};
|
||||
break;
|
||||
case "eventTimings":
|
||||
expectedPacket = {
|
||||
totalTime: /^\d+$/,
|
||||
};
|
||||
break;
|
||||
default:
|
||||
ok(false, "unknown network event update type: " +
|
||||
aPacket.updateType);
|
||||
return;
|
||||
}
|
||||
|
||||
if (expectedPacket) {
|
||||
info("checking the packet content");
|
||||
checkObject(aPacket, expectedPacket);
|
||||
}
|
||||
|
||||
if (updates.indexOf("responseContent") > -1 &&
|
||||
updates.indexOf("eventTimings") > -1) {
|
||||
aState.dbgClient.removeListener("networkEventUpdate",
|
||||
onNetworkEvent);
|
||||
|
||||
onRequestHeaders = onRequestHeaders.bind(null, aState);
|
||||
aState.client.getRequestHeaders(aState.netActor,
|
||||
onRequestHeaders);
|
||||
}
|
||||
}
|
||||
|
||||
function onRequestHeaders(aState, aResponse)
|
||||
{
|
||||
info("checking request headers");
|
||||
|
||||
ok(aResponse.headers.length > 0, "request headers > 0");
|
||||
ok(aResponse.headersSize > 0, "request headersSize > 0");
|
||||
|
||||
checkHeadersOrCookies(aResponse.headers, {
|
||||
Referer: /network_requests_iframe\.html/,
|
||||
Cookie: /bug768096/,
|
||||
});
|
||||
|
||||
onRequestCookies = onRequestCookies.bind(null, aState);
|
||||
aState.client.getRequestCookies(aState.netActor,
|
||||
onRequestCookies);
|
||||
}
|
||||
|
||||
function onRequestCookies(aState, aResponse)
|
||||
{
|
||||
info("checking request cookies");
|
||||
|
||||
is(aResponse.cookies.length, 2, "request cookies length");
|
||||
|
||||
checkHeadersOrCookies(aResponse.cookies, {
|
||||
foobar: "fooval",
|
||||
omgfoo: "bug768096",
|
||||
});
|
||||
|
||||
onRequestPostData = onRequestPostData.bind(null, aState);
|
||||
aState.client.getRequestPostData(aState.netActor,
|
||||
onRequestPostData);
|
||||
}
|
||||
|
||||
function onRequestPostData(aState, aResponse)
|
||||
{
|
||||
info("checking request POST data");
|
||||
|
||||
checkObject(aResponse, {
|
||||
postData: {
|
||||
text: "Hello world!",
|
||||
},
|
||||
postDataDiscarded: false,
|
||||
});
|
||||
|
||||
onResponseHeaders = onResponseHeaders.bind(null, aState);
|
||||
aState.client.getResponseHeaders(aState.netActor,
|
||||
onResponseHeaders);
|
||||
}
|
||||
|
||||
function onResponseHeaders(aState, aResponse)
|
||||
{
|
||||
info("checking response headers");
|
||||
|
||||
ok(aResponse.headers.length > 0, "response headers > 0");
|
||||
ok(aResponse.headersSize > 0, "response headersSize > 0");
|
||||
|
||||
checkHeadersOrCookies(aResponse.headers, {
|
||||
"Content-Type": /^application\/(json|octet-stream)$/,
|
||||
"Content-Length": /^\d+$/,
|
||||
});
|
||||
|
||||
onResponseCookies = onResponseCookies.bind(null, aState);
|
||||
aState.client.getResponseCookies(aState.netActor,
|
||||
onResponseCookies);
|
||||
}
|
||||
|
||||
function onResponseCookies(aState, aResponse)
|
||||
{
|
||||
info("checking response cookies");
|
||||
|
||||
is(aResponse.cookies.length, 0, "response cookies length");
|
||||
|
||||
onResponseContent = onResponseContent.bind(null, aState);
|
||||
aState.client.getResponseContent(aState.netActor,
|
||||
onResponseContent);
|
||||
}
|
||||
|
||||
function onResponseContent(aState, aResponse)
|
||||
{
|
||||
info("checking response content");
|
||||
|
||||
checkObject(aResponse, {
|
||||
content: {
|
||||
text: /"test JSON data"/,
|
||||
},
|
||||
contentDiscarded: false,
|
||||
});
|
||||
|
||||
onEventTimings = onEventTimings.bind(null, aState);
|
||||
aState.client.getEventTimings(aState.netActor,
|
||||
onEventTimings);
|
||||
}
|
||||
|
||||
function onEventTimings(aState, aResponse)
|
||||
{
|
||||
info("checking event timings");
|
||||
|
||||
checkObject(aResponse, {
|
||||
timings: {
|
||||
blocked: /^-1|\d+$/,
|
||||
dns: /^-1|\d+$/,
|
||||
connect: /^-1|\d+$/,
|
||||
send: /^-1|\d+$/,
|
||||
wait: /^-1|\d+$/,
|
||||
receive: /^-1|\d+$/,
|
||||
},
|
||||
totalTime: /^\d+$/,
|
||||
});
|
||||
|
||||
closeDebugger(aState, function() {
|
||||
SimpleTest.finish();
|
||||
});
|
||||
}
|
||||
|
||||
addEventListener("load", startTest);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,171 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf8">
|
||||
<title>Test for the object actor</title>
|
||||
<script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript;version=1.8" src="common.js"></script>
|
||||
<!-- Any copyright is dedicated to the Public Domain.
|
||||
- http://creativecommons.org/publicdomain/zero/1.0/ -->
|
||||
</head>
|
||||
<body>
|
||||
<p>Test for the object actor</p>
|
||||
|
||||
<script class="testbody" type="text/javascript;version=1.8">
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
let expectedProps = [];
|
||||
|
||||
function startTest()
|
||||
{
|
||||
removeEventListener("load", startTest);
|
||||
|
||||
attachConsole(["ConsoleAPI"], onAttach, true);
|
||||
}
|
||||
|
||||
function onAttach(aState, aResponse)
|
||||
{
|
||||
onConsoleCall = onConsoleCall.bind(null, aState);
|
||||
aState.dbgClient.addListener("consoleAPICall", onConsoleCall);
|
||||
|
||||
window.foobarObject = Object.create(null);
|
||||
foobarObject.foo = 1;
|
||||
foobarObject.foobar = "hello";
|
||||
foobarObject.foobaz = document;
|
||||
foobarObject.omg = null;
|
||||
foobarObject.testfoo = false;
|
||||
foobarObject.notInspectable = {};
|
||||
foobarObject.omgfn = function _omgfn() {
|
||||
return "myResult";
|
||||
};
|
||||
foobarObject.abArray = ["a", "b"];
|
||||
|
||||
Object.defineProperty(foobarObject, "getterAndSetter", {
|
||||
enumerable: true,
|
||||
get: function fooGet() { return "foo"; },
|
||||
set: function fooSet() { 1+2 },
|
||||
});
|
||||
|
||||
console.log("hello", foobarObject);
|
||||
|
||||
expectedProps = [
|
||||
{
|
||||
name: "abArray",
|
||||
value: {
|
||||
type: "object",
|
||||
className: "Array",
|
||||
actor: /[a-z]/,
|
||||
inspectable: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "foo",
|
||||
configurable: true,
|
||||
enumerable: true,
|
||||
writable: true,
|
||||
value: 1,
|
||||
},
|
||||
{
|
||||
name: "foobar",
|
||||
value: "hello",
|
||||
},
|
||||
{
|
||||
name: "foobaz",
|
||||
value: {
|
||||
type: "object",
|
||||
className: "HTMLDocument",
|
||||
displayString: /\[object HTMLDocument/,
|
||||
inspectable: true,
|
||||
actor: /[a-z]/,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "getterAndSetter",
|
||||
get: {
|
||||
type: "function",
|
||||
className: "function",
|
||||
displayString: /function fooGet/,
|
||||
actor: /[a-z]/,
|
||||
inspectable: false,
|
||||
},
|
||||
set: {
|
||||
type: "function",
|
||||
className: "function",
|
||||
displayString: /function fooSet/,
|
||||
actor: /[a-z]/,
|
||||
inspectable: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "notInspectable",
|
||||
value: {
|
||||
type: "object",
|
||||
className: "Object",
|
||||
actor: /[a-z]/,
|
||||
inspectable: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "omg",
|
||||
value: { type: "null" },
|
||||
},
|
||||
{
|
||||
name: "omgfn",
|
||||
value: {
|
||||
type: "function",
|
||||
className: "function",
|
||||
displayString: /function _omgfn/,
|
||||
actor: /[a-z]/,
|
||||
inspectable: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "testfoo",
|
||||
value: false,
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
function onConsoleCall(aState, aType, aPacket)
|
||||
{
|
||||
is(aPacket.from, aState.actor, "console API call actor");
|
||||
|
||||
info("checking the console API call packet");
|
||||
|
||||
checkConsoleAPICall(aPacket.message, {
|
||||
level: "log",
|
||||
filename: /test_object_actor/,
|
||||
functionName: "onAttach",
|
||||
arguments: ["hello", {
|
||||
type: "object",
|
||||
actor: /[a-z]/,
|
||||
inspectable: true,
|
||||
}],
|
||||
});
|
||||
|
||||
aState.dbgClient.removeListener("consoleAPICall", onConsoleCall);
|
||||
|
||||
info("inspecting object properties");
|
||||
let args = aPacket.message.arguments;
|
||||
onProperties = onProperties.bind(null, aState);
|
||||
aState.client.inspectObjectProperties(args[1].actor, onProperties);
|
||||
}
|
||||
|
||||
function onProperties(aState, aResponse)
|
||||
{
|
||||
let props = aResponse.properties;
|
||||
is(props.length, expectedProps.length,
|
||||
"number of enumerable properties");
|
||||
checkObject(props, expectedProps);
|
||||
|
||||
expectedProps = [];
|
||||
|
||||
closeDebugger(aState, function() {
|
||||
SimpleTest.finish();
|
||||
});
|
||||
}
|
||||
|
||||
addEventListener("load", startTest);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,97 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf8">
|
||||
<title>Test for page errors</title>
|
||||
<script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript;version=1.8" src="common.js"></script>
|
||||
<!-- Any copyright is dedicated to the Public Domain.
|
||||
- http://creativecommons.org/publicdomain/zero/1.0/ -->
|
||||
</head>
|
||||
<body>
|
||||
<p>Test for page errors</p>
|
||||
|
||||
<script class="testbody" type="text/javascript;version=1.8">
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
let expectedPageErrors = [];
|
||||
|
||||
function doPageErrors()
|
||||
{
|
||||
expectedPageErrors = [
|
||||
{
|
||||
errorMessage: /fooColor/,
|
||||
sourceName: /test_page_errors/,
|
||||
category: "CSS Parser",
|
||||
timeStamp: /^\d+$/,
|
||||
error: false,
|
||||
warning: true,
|
||||
exception: false,
|
||||
strict: false,
|
||||
},
|
||||
{
|
||||
errorMessage: /doTheImpossible/,
|
||||
sourceName: /test_page_errors/,
|
||||
category: "chrome javascript",
|
||||
timeStamp: /^\d+$/,
|
||||
error: false,
|
||||
warning: false,
|
||||
exception: true,
|
||||
strict: false,
|
||||
},
|
||||
];
|
||||
|
||||
let container = document.createElement("script");
|
||||
document.body.appendChild(container);
|
||||
container.textContent = "document.body.style.color = 'fooColor';";
|
||||
document.body.removeChild(container);
|
||||
|
||||
SimpleTest.expectUncaughtException();
|
||||
|
||||
container = document.createElement("script");
|
||||
document.body.appendChild(container);
|
||||
container.textContent = "document.doTheImpossible();";
|
||||
document.body.removeChild(container);
|
||||
}
|
||||
|
||||
function startTest()
|
||||
{
|
||||
removeEventListener("load", startTest);
|
||||
|
||||
attachConsole(["PageError"], onAttach);
|
||||
}
|
||||
|
||||
function onAttach(aState, aResponse)
|
||||
{
|
||||
onPageError = onPageError.bind(null, aState);
|
||||
aState.dbgClient.addListener("pageError", onPageError);
|
||||
doPageErrors();
|
||||
}
|
||||
|
||||
let pageErrors = [];
|
||||
|
||||
function onPageError(aState, aType, aPacket)
|
||||
{
|
||||
is(aPacket.from, aState.actor, "page error actor");
|
||||
|
||||
pageErrors.push(aPacket.pageError);
|
||||
if (pageErrors.length != expectedPageErrors.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
aState.dbgClient.removeListener("pageError", onPageError);
|
||||
|
||||
expectedPageErrors.forEach(function(aMessage, aIndex) {
|
||||
info("checking received page error #" + aIndex);
|
||||
checkObject(pageErrors[aIndex], expectedPageErrors[aIndex]);
|
||||
});
|
||||
|
||||
closeDebugger(aState, function() {
|
||||
SimpleTest.finish();
|
||||
});
|
||||
}
|
||||
|
||||
addEventListener("load", startTest);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
Загрузка…
Ссылка в новой задаче