зеркало из https://github.com/mozilla/gecko-dev.git
Merge fx-team to m-c
This commit is contained in:
Коммит
6ebed5316f
|
@ -1013,8 +1013,9 @@ pref("services.sync.prefs.sync.xpinstall.whitelist.required", true);
|
||||||
// Disable the error console
|
// Disable the error console
|
||||||
pref("devtools.errorconsole.enabled", false);
|
pref("devtools.errorconsole.enabled", false);
|
||||||
|
|
||||||
// Enable the developer toolbar
|
// Developer toolbar and GCLI preferences
|
||||||
pref("devtools.toolbar.enabled", false);
|
pref("devtools.toolbar.enabled", false);
|
||||||
|
pref("devtools.gcli.allowSet", false);
|
||||||
|
|
||||||
// Enable the Inspector
|
// Enable the Inspector
|
||||||
pref("devtools.inspector.enabled", true);
|
pref("devtools.inspector.enabled", true);
|
||||||
|
|
|
@ -292,7 +292,7 @@ let TabView = {
|
||||||
// if group has title, it's not hidden and there is no active group or
|
// if group has title, it's not hidden and there is no active group or
|
||||||
// the active group id doesn't match the group id, a group menu item
|
// the active group id doesn't match the group id, a group menu item
|
||||||
// would be added.
|
// would be added.
|
||||||
if (groupItem.getTitle().length > 0 && !groupItem.hidden &&
|
if (!groupItem.hidden && groupItem.getChildren().length &&
|
||||||
(!activeGroup || activeGroup.id != groupItem.id)) {
|
(!activeGroup || activeGroup.id != groupItem.id)) {
|
||||||
let menuItem = self._createGroupMenuItem(groupItem);
|
let menuItem = self._createGroupMenuItem(groupItem);
|
||||||
popup.insertBefore(menuItem, separator);
|
popup.insertBefore(menuItem, separator);
|
||||||
|
@ -305,8 +305,25 @@ let TabView = {
|
||||||
|
|
||||||
// ----------
|
// ----------
|
||||||
_createGroupMenuItem: function TabView__createGroupMenuItem(groupItem) {
|
_createGroupMenuItem: function TabView__createGroupMenuItem(groupItem) {
|
||||||
let menuItem = document.createElement("menuitem")
|
let menuItem = document.createElement("menuitem");
|
||||||
menuItem.setAttribute("label", groupItem.getTitle());
|
let title = groupItem.getTitle();
|
||||||
|
|
||||||
|
if (!title.trim()) {
|
||||||
|
let topChildLabel = groupItem.getTopChild().tab.label;
|
||||||
|
|
||||||
|
if (groupItem.getChildren().length > 1) {
|
||||||
|
title =
|
||||||
|
gNavigatorBundle.getFormattedString("tabview2.moveToUnnamedGroup.label",
|
||||||
|
[topChildLabel, groupItem.getChildren().length - 1]);
|
||||||
|
} else {
|
||||||
|
title = topChildLabel;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
menuItem.setAttribute("label", title);
|
||||||
|
menuItem.setAttribute("tooltiptext", title);
|
||||||
|
menuItem.setAttribute("crop", "center");
|
||||||
|
menuItem.setAttribute("class", "tabview-menuitem");
|
||||||
menuItem.setAttribute(
|
menuItem.setAttribute(
|
||||||
"oncommand",
|
"oncommand",
|
||||||
"TabView.moveTabTo(TabContextMenu.contextTab,'" + groupItem.id + "')");
|
"TabView.moveTabTo(TabContextMenu.contextTab,'" + groupItem.id + "')");
|
||||||
|
|
|
@ -545,5 +545,10 @@ statuspanel[inactive][previoustype=overLink] {
|
||||||
-moz-binding: url("chrome://browser/content/urlbarBindings.xml#promobox");
|
-moz-binding: url("chrome://browser/content/urlbarBindings.xml#promobox");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* tabview menus */
|
||||||
|
.tabview-menuitem {
|
||||||
|
max-width: 32em;
|
||||||
|
}
|
||||||
|
|
||||||
/* highlighter */
|
/* highlighter */
|
||||||
%include highlighter.css
|
%include highlighter.css
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
|
||||||
let EXPORTED_SYMBOLS = [ "GcliCommands" ];
|
let EXPORTED_SYMBOLS = [ ];
|
||||||
|
|
||||||
Components.utils.import("resource:///modules/devtools/gcli.jsm");
|
Components.utils.import("resource:///modules/devtools/gcli.jsm");
|
||||||
Components.utils.import("resource:///modules/HUDService.jsm");
|
Components.utils.import("resource:///modules/HUDService.jsm");
|
||||||
|
|
|
@ -65,7 +65,7 @@ var mozl10n = {};
|
||||||
|
|
||||||
})(mozl10n);
|
})(mozl10n);
|
||||||
|
|
||||||
define('gcli/index', ['require', 'exports', 'module' , 'gcli/types/basic', 'gcli/types/command', 'gcli/types/javascript', 'gcli/types/node', 'gcli/types/resource', 'gcli/types/setting', 'gcli/types/selection', 'gcli/settings', 'gcli/ui/intro', 'gcli/ui/focus', 'gcli/ui/fields/basic', 'gcli/ui/fields/javascript', 'gcli/ui/fields/selection', 'gcli/commands/help', 'gcli/canon', 'gcli/ui/ffdisplay'], function(require, exports, module) {
|
define('gcli/index', ['require', 'exports', 'module' , 'gcli/types/basic', 'gcli/types/command', 'gcli/types/javascript', 'gcli/types/node', 'gcli/types/resource', 'gcli/types/setting', 'gcli/types/selection', 'gcli/settings', 'gcli/ui/intro', 'gcli/ui/focus', 'gcli/ui/fields/basic', 'gcli/ui/fields/javascript', 'gcli/ui/fields/selection', 'gcli/commands/help', 'gcli/commands/pref', 'gcli/canon', 'gcli/ui/ffdisplay'], function(require, exports, module) {
|
||||||
|
|
||||||
// Internal startup process. Not exported
|
// Internal startup process. Not exported
|
||||||
require('gcli/types/basic').startup();
|
require('gcli/types/basic').startup();
|
||||||
|
@ -84,6 +84,7 @@ define('gcli/index', ['require', 'exports', 'module' , 'gcli/types/basic', 'gcli
|
||||||
require('gcli/ui/fields/selection').startup();
|
require('gcli/ui/fields/selection').startup();
|
||||||
|
|
||||||
require('gcli/commands/help').startup();
|
require('gcli/commands/help').startup();
|
||||||
|
require('gcli/commands/pref').startup();
|
||||||
|
|
||||||
// The API for use by command authors
|
// The API for use by command authors
|
||||||
exports.addCommand = require('gcli/canon').addCommand;
|
exports.addCommand = require('gcli/canon').addCommand;
|
||||||
|
@ -1674,7 +1675,7 @@ exports.Speller = Speller;
|
||||||
* http://opensource.org/licenses/BSD-3-Clause
|
* http://opensource.org/licenses/BSD-3-Clause
|
||||||
*/
|
*/
|
||||||
|
|
||||||
define('gcli/types/selection', ['require', 'exports', 'module' , 'gcli/l10n', 'gcli/types', 'gcli/types/spell', 'gcli/argument'], function(require, exports, module) {
|
define('gcli/types/selection', ['require', 'exports', 'module' , 'gcli/l10n', 'gcli/types', 'gcli/types/spell'], function(require, exports, module) {
|
||||||
|
|
||||||
|
|
||||||
var l10n = require('gcli/l10n');
|
var l10n = require('gcli/l10n');
|
||||||
|
@ -1683,7 +1684,6 @@ var Type = require('gcli/types').Type;
|
||||||
var Status = require('gcli/types').Status;
|
var Status = require('gcli/types').Status;
|
||||||
var Conversion = require('gcli/types').Conversion;
|
var Conversion = require('gcli/types').Conversion;
|
||||||
var Speller = require('gcli/types/spell').Speller;
|
var Speller = require('gcli/types/spell').Speller;
|
||||||
var Argument = require('gcli/argument').Argument;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1714,6 +1714,9 @@ exports.shutdown = function() {
|
||||||
* the associated name. However the name maybe available directly from the
|
* the associated name. However the name maybe available directly from the
|
||||||
* value using a property lookup. Setting 'stringifyProperty' allows
|
* value using a property lookup. Setting 'stringifyProperty' allows
|
||||||
* SelectionType to take this shortcut.
|
* SelectionType to take this shortcut.
|
||||||
|
* - cacheable : If lookup is a function, then we normally assume that
|
||||||
|
* the values fetched can change. Setting 'cacheable' enables internal
|
||||||
|
* caching.
|
||||||
*/
|
*/
|
||||||
function SelectionType(typeSpec) {
|
function SelectionType(typeSpec) {
|
||||||
if (typeSpec) {
|
if (typeSpec) {
|
||||||
|
@ -1743,14 +1746,30 @@ SelectionType.prototype.stringify = function(value) {
|
||||||
return name;
|
return name;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If typeSpec contained cacheable:true then calls to parse() work on cached
|
||||||
|
* data. clearCache() enables the cache to be cleared.
|
||||||
|
*/
|
||||||
|
SelectionType.prototype.clearCache = function() {
|
||||||
|
delete this._cachedLookup;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* There are several ways to get selection data. This unifies them into one
|
* There are several ways to get selection data. This unifies them into one
|
||||||
* single function.
|
* single function.
|
||||||
* @return An array of objects with name and value properties.
|
* @return An array of objects with name and value properties.
|
||||||
*/
|
*/
|
||||||
SelectionType.prototype.getLookup = function() {
|
SelectionType.prototype.getLookup = function() {
|
||||||
|
if (this._cachedLookup) {
|
||||||
|
return this._cachedLookup;
|
||||||
|
}
|
||||||
|
|
||||||
if (this.lookup) {
|
if (this.lookup) {
|
||||||
if (typeof this.lookup === 'function') {
|
if (typeof this.lookup === 'function') {
|
||||||
|
if (this.cacheable) {
|
||||||
|
this._cachedLookup = this.lookup();
|
||||||
|
return this._cachedLookup;
|
||||||
|
}
|
||||||
return this.lookup();
|
return this.lookup();
|
||||||
}
|
}
|
||||||
return this.lookup;
|
return this.lookup;
|
||||||
|
@ -2257,8 +2276,6 @@ Parameter.prototype.isKnownAs = function(name) {
|
||||||
* parseString on an empty string
|
* parseString on an empty string
|
||||||
*/
|
*/
|
||||||
Parameter.prototype.getBlank = function() {
|
Parameter.prototype.getBlank = function() {
|
||||||
var conversion;
|
|
||||||
|
|
||||||
if (this.type.getBlank) {
|
if (this.type.getBlank) {
|
||||||
return this.type.getBlank();
|
return this.type.getBlank();
|
||||||
}
|
}
|
||||||
|
@ -2357,13 +2374,19 @@ canon.addCommand = function addCommand(commandSpec) {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove an individual command. The opposite of #addCommand().
|
* Remove an individual command. The opposite of #addCommand().
|
||||||
|
* Removing a non-existent command is a no-op.
|
||||||
* @param commandOrName Either a command name or the command itself.
|
* @param commandOrName Either a command name or the command itself.
|
||||||
|
* @return true if a command was removed, false otherwise.
|
||||||
*/
|
*/
|
||||||
canon.removeCommand = function removeCommand(commandOrName) {
|
canon.removeCommand = function removeCommand(commandOrName) {
|
||||||
var name = typeof commandOrName === 'string' ?
|
var name = typeof commandOrName === 'string' ?
|
||||||
commandOrName :
|
commandOrName :
|
||||||
commandOrName.name;
|
commandOrName.name;
|
||||||
|
|
||||||
|
if (!commands[name]) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// See start of canon.addCommand if changing this code
|
// See start of canon.addCommand if changing this code
|
||||||
delete commands[name];
|
delete commands[name];
|
||||||
delete commandSpecs[name];
|
delete commandSpecs[name];
|
||||||
|
@ -2372,6 +2395,7 @@ canon.removeCommand = function removeCommand(commandOrName) {
|
||||||
});
|
});
|
||||||
|
|
||||||
canon.onCanonChange();
|
canon.onCanonChange();
|
||||||
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -2941,6 +2965,56 @@ exports.createUrlLookup = function(callingModule) {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper to find the 'data-command' attribute and call some action on it.
|
||||||
|
* @see |updateCommand()| and |executeCommand()|
|
||||||
|
*/
|
||||||
|
function withCommand(element, action) {
|
||||||
|
var command = element.getAttribute('data-command');
|
||||||
|
if (!command) {
|
||||||
|
command = element.querySelector('*[data-command]')
|
||||||
|
.getAttribute('data-command');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (command) {
|
||||||
|
action(command);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
console.warn('Missing data-command for ' + util.findCssSelector(element));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the requisition to contain the text of the clicked element
|
||||||
|
* @param element The clicked element, containing either a data-command
|
||||||
|
* attribute directly or in a nested element, from which we get the command
|
||||||
|
* to be executed.
|
||||||
|
* @param context Either a Requisition or an ExecutionContext or another object
|
||||||
|
* that contains an |update()| function that follows a similar contract.
|
||||||
|
*/
|
||||||
|
exports.updateCommand = function(element, context) {
|
||||||
|
withCommand(element, function(command) {
|
||||||
|
context.update(command);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute the text contained in the element that was clicked
|
||||||
|
* @param element The clicked element, containing either a data-command
|
||||||
|
* attribute directly or in a nested element, from which we get the command
|
||||||
|
* to be executed.
|
||||||
|
* @param context Either a Requisition or an ExecutionContext or another object
|
||||||
|
* that contains an |update()| function that follows a similar contract.
|
||||||
|
*/
|
||||||
|
exports.executeCommand = function(element, context) {
|
||||||
|
withCommand(element, function(command) {
|
||||||
|
context.exec({
|
||||||
|
visible: true,
|
||||||
|
typed: command
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
@ -4136,9 +4210,13 @@ function SettingType(typeSpec) {
|
||||||
if (Object.keys(typeSpec).length > 0) {
|
if (Object.keys(typeSpec).length > 0) {
|
||||||
throw new Error('SettingType can not be customized');
|
throw new Error('SettingType can not be customized');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
settings.onChange.add(function(ev) {
|
||||||
|
this.clearCache();
|
||||||
|
}, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
SettingType.prototype = Object.create(SelectionType.prototype);
|
SettingType.prototype = new SelectionType({ cacheable: true });
|
||||||
|
|
||||||
SettingType.prototype.lookup = function() {
|
SettingType.prototype.lookup = function() {
|
||||||
return settings.getAll().map(function(setting) {
|
return settings.getAll().map(function(setting) {
|
||||||
|
@ -4219,8 +4297,7 @@ var types = require('gcli/types');
|
||||||
var allSettings = [];
|
var allSettings = [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* No setup required because settings are pre-loaded with Mozilla,
|
* Cache existing settings on startup
|
||||||
* but match API with main settings.js
|
|
||||||
*/
|
*/
|
||||||
exports.startup = function() {
|
exports.startup = function() {
|
||||||
imports.prefBranch.getChildList('').forEach(function(name) {
|
imports.prefBranch.getChildList('').forEach(function(name) {
|
||||||
|
@ -4304,9 +4381,8 @@ Object.defineProperty(Setting.prototype, 'value', {
|
||||||
case imports.prefBranch.PREF_STRING:
|
case imports.prefBranch.PREF_STRING:
|
||||||
var value = imports.prefBranch.getComplexValue(this.name,
|
var value = imports.prefBranch.getComplexValue(this.name,
|
||||||
Components.interfaces.nsISupportsString).data;
|
Components.interfaces.nsISupportsString).data;
|
||||||
// Try in case it's a localized string (will throw an exception if not)
|
// In case of a localized string
|
||||||
var isL10n = /^chrome:\/\/.+\/locale\/.+\.properties/.test(value);
|
if (/^chrome:\/\/.+\/locale\/.+\.properties/.test(value)) {
|
||||||
if (!this.changed && isL10n) {
|
|
||||||
value = imports.prefBranch.getComplexValue(this.name,
|
value = imports.prefBranch.getComplexValue(this.name,
|
||||||
Components.interfaces.nsIPrefLocalizedString).data;
|
Components.interfaces.nsIPrefLocalizedString).data;
|
||||||
}
|
}
|
||||||
|
@ -4348,6 +4424,13 @@ Object.defineProperty(Setting.prototype, 'value', {
|
||||||
enumerable: true
|
enumerable: true
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reset this setting to it's initial default value
|
||||||
|
*/
|
||||||
|
Setting.prototype.setDefault = function() {
|
||||||
|
imports.prefBranch.clearUserPref(this.name);
|
||||||
|
Services.prefs.savePrefFile(null);
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 'static' function to get an array containing all known Settings
|
* 'static' function to get an array containing all known Settings
|
||||||
|
@ -4371,9 +4454,36 @@ exports.addSetting = function(prefSpec) {
|
||||||
allSettings[i] = setting;
|
allSettings[i] = setting;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
exports.onChange({ added: setting.name });
|
||||||
return setting;
|
return setting;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Getter for an existing setting. Generally use of this function should be
|
||||||
|
* avoided. Systems that define a setting should export it if they wish it to
|
||||||
|
* be available to the outside, or not otherwise. Use of this function breaks
|
||||||
|
* that boundary and also hides dependencies. Acceptable uses include testing
|
||||||
|
* and embedded uses of GCLI that pre-define all settings (e.g. Firefox)
|
||||||
|
* @param name The name of the setting to fetch
|
||||||
|
* @return The found Setting object, or undefined if the setting was not found
|
||||||
|
*/
|
||||||
|
exports.getSetting = function(name) {
|
||||||
|
var found = undefined;
|
||||||
|
allSettings.some(function(setting) {
|
||||||
|
if (setting.name === name) {
|
||||||
|
found = setting;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
return found;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Event for use to detect when the list of settings changes
|
||||||
|
*/
|
||||||
|
exports.onChange = util.createEvent('Settings.onChange');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove a setting. A no-op in this case
|
* Remove a setting. A no-op in this case
|
||||||
*/
|
*/
|
||||||
|
@ -4388,10 +4498,11 @@ exports.removeSetting = function(nameOrSpec) {
|
||||||
* http://opensource.org/licenses/BSD-3-Clause
|
* http://opensource.org/licenses/BSD-3-Clause
|
||||||
*/
|
*/
|
||||||
|
|
||||||
define('gcli/ui/intro', ['require', 'exports', 'module' , 'gcli/settings', 'gcli/l10n', 'gcli/ui/view', 'gcli/cli', 'text!gcli/ui/intro.html'], function(require, exports, module) {
|
define('gcli/ui/intro', ['require', 'exports', 'module' , 'gcli/settings', 'gcli/l10n', 'gcli/util', 'gcli/ui/view', 'gcli/cli', 'text!gcli/ui/intro.html'], function(require, exports, module) {
|
||||||
|
|
||||||
var settings = require('gcli/settings');
|
var settings = require('gcli/settings');
|
||||||
var l10n = require('gcli/l10n');
|
var l10n = require('gcli/l10n');
|
||||||
|
var util = require('gcli/util');
|
||||||
var view = require('gcli/ui/view');
|
var view = require('gcli/ui/view');
|
||||||
var Output = require('gcli/cli').Output;
|
var Output = require('gcli/cli').Output;
|
||||||
|
|
||||||
|
@ -4421,7 +4532,7 @@ define('gcli/ui/intro', ['require', 'exports', 'module' , 'gcli/settings', 'gcli
|
||||||
/**
|
/**
|
||||||
* Called when the UI is ready to add a welcome message to the output
|
* Called when the UI is ready to add a welcome message to the output
|
||||||
*/
|
*/
|
||||||
exports.maybeShowIntro = function(commandOutputManager) {
|
exports.maybeShowIntro = function(commandOutputManager, context) {
|
||||||
if (hideIntro.value) {
|
if (hideIntro.value) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -4429,18 +4540,33 @@ define('gcli/ui/intro', ['require', 'exports', 'module' , 'gcli/settings', 'gcli
|
||||||
var output = new Output();
|
var output = new Output();
|
||||||
commandOutputManager.onOutput({ output: output });
|
commandOutputManager.onOutput({ output: output });
|
||||||
|
|
||||||
var viewData = view.createView({
|
var viewData = this.createView(context, output);
|
||||||
|
|
||||||
|
output.complete(viewData);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when the UI is ready to add a welcome message to the output
|
||||||
|
*/
|
||||||
|
exports.createView = function(context, output) {
|
||||||
|
return view.createView({
|
||||||
html: require('text!gcli/ui/intro.html'),
|
html: require('text!gcli/ui/intro.html'),
|
||||||
|
options: { stack: 'intro.html' },
|
||||||
data: {
|
data: {
|
||||||
showHideButton: true,
|
l10n: l10n.propertyLookup,
|
||||||
|
onclick: function(ev) {
|
||||||
|
util.updateCommand(ev.currentTarget, context);
|
||||||
|
},
|
||||||
|
ondblclick: function(ev) {
|
||||||
|
util.executeCommand(ev.currentTarget, context);
|
||||||
|
},
|
||||||
|
showHideButton: (output != null),
|
||||||
onGotIt: function(ev) {
|
onGotIt: function(ev) {
|
||||||
hideIntro.value = true;
|
hideIntro.value = true;
|
||||||
output.onClose();
|
output.onClose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
output.complete(viewData);
|
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
/*
|
/*
|
||||||
|
@ -6097,6 +6223,12 @@ Output.prototype.toDom = function(element) {
|
||||||
util.setContents(node, output.toString());
|
util.setContents(node, output.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Make sure that links open in a new window.
|
||||||
|
var links = node.querySelectorAll('*[href]');
|
||||||
|
for (var i = 0; i < links.length; i++) {
|
||||||
|
links[i].setAttribute('target', '_blank');
|
||||||
|
}
|
||||||
|
|
||||||
element.appendChild(node);
|
element.appendChild(node);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -6155,17 +6287,16 @@ define('gcli/promise', ['require', 'exports', 'module' ], function(require, expo
|
||||||
});
|
});
|
||||||
define("text!gcli/ui/intro.html", [], "\n" +
|
define("text!gcli/ui/intro.html", [], "\n" +
|
||||||
"<div>\n" +
|
"<div>\n" +
|
||||||
|
" <p>${l10n.introTextOpening}</p>\n" +
|
||||||
|
"\n" +
|
||||||
" <p>\n" +
|
" <p>\n" +
|
||||||
" GCLI is an experiment to create a highly usable <strong>graphical command\n" +
|
" ${l10n.introTextCommands}\n" +
|
||||||
" line</strong> for developers. It's not a JavaScript\n" +
|
" <span class=\"gcli-out-shortcut\" onclick=\"${onclick}\"\n" +
|
||||||
" <a href=\"https://en.wikipedia.org/wiki/Read<61>eval<61>print_loop\">REPL</a>, so\n" +
|
" ondblclick=\"${ondblclick}\" data-command=\"help\">help</span>,\n" +
|
||||||
" it focuses on speed of input over JavaScript syntax and a rich display over\n" +
|
" ${l10n.introTextKeys} <code>${l10n.introTextF1Escape}</code>.\n" +
|
||||||
" monospace output.</p>\n" +
|
" </p>\n" +
|
||||||
"\n" +
|
"\n" +
|
||||||
" <p>Type <span class=\"gcli-out-shortcut\">help</span> for a list of commands,\n" +
|
" <button onclick=\"${onGotIt}\" if=\"${showHideButton}\">${l10n.introTextGo}</button>\n" +
|
||||||
" or press <code>F1/Escape</code> to show/hide command hints.</p>\n" +
|
|
||||||
"\n" +
|
|
||||||
" <button onclick=\"${onGotIt}\" if=\"${showHideButton}\">Got it!</button>\n" +
|
|
||||||
"</div>\n" +
|
"</div>\n" +
|
||||||
"");
|
"");
|
||||||
|
|
||||||
|
@ -7729,12 +7860,13 @@ SelectionTooltipField.DEFAULT_VALUE = '__SelectionTooltipField.DEFAULT_VALUE';
|
||||||
* http://opensource.org/licenses/BSD-3-Clause
|
* http://opensource.org/licenses/BSD-3-Clause
|
||||||
*/
|
*/
|
||||||
|
|
||||||
define('gcli/commands/help', ['require', 'exports', 'module' , 'gcli/canon', 'gcli/l10n', 'gcli/ui/view', 'text!gcli/commands/help_man.html', 'text!gcli/commands/help_list.html', 'text!gcli/commands/help.css'], function(require, exports, module) {
|
define('gcli/commands/help', ['require', 'exports', 'module' , 'gcli/canon', 'gcli/l10n', 'gcli/util', 'gcli/ui/view', 'text!gcli/commands/help_man.html', 'text!gcli/commands/help_list.html', 'text!gcli/commands/help.css'], function(require, exports, module) {
|
||||||
var help = exports;
|
var help = exports;
|
||||||
|
|
||||||
|
|
||||||
var canon = require('gcli/canon');
|
var canon = require('gcli/canon');
|
||||||
var l10n = require('gcli/l10n');
|
var l10n = require('gcli/l10n');
|
||||||
|
var util = require('gcli/util');
|
||||||
var view = require('gcli/ui/view');
|
var view = require('gcli/ui/view');
|
||||||
|
|
||||||
// Storing the HTML on exports allows other builds to alter the help template
|
// Storing the HTML on exports allows other builds to alter the help template
|
||||||
|
@ -7794,26 +7926,6 @@ help.shutdown = function() {
|
||||||
canon.removeCommand(helpCommandSpec);
|
canon.removeCommand(helpCommandSpec);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Find an element within the passed element with the class gcli-help-command
|
|
||||||
* and update the requisition to contain this text.
|
|
||||||
*/
|
|
||||||
function updateCommand(element, context) {
|
|
||||||
var typed = element.querySelector('.gcli-help-command').textContent;
|
|
||||||
context.update(typed);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Find an element within the passed element with the class gcli-help-command
|
|
||||||
* and execute this text.
|
|
||||||
*/
|
|
||||||
function executeCommand(element, context) {
|
|
||||||
context.exec({
|
|
||||||
visible: true,
|
|
||||||
typed: element.querySelector('.gcli-help-command').textContent
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a block of data suitable to be passed to the help_list.html template
|
* Create a block of data suitable to be passed to the help_list.html template
|
||||||
*/
|
*/
|
||||||
|
@ -7823,11 +7935,11 @@ function getListTemplateData(args, context) {
|
||||||
includeIntro: args.search == null,
|
includeIntro: args.search == null,
|
||||||
|
|
||||||
onclick: function(ev) {
|
onclick: function(ev) {
|
||||||
updateCommand(ev.currentTarget, context);
|
util.updateCommand(ev.currentTarget, context);
|
||||||
},
|
},
|
||||||
|
|
||||||
ondblclick: function(ev) {
|
ondblclick: function(ev) {
|
||||||
executeCommand(ev.currentTarget, context);
|
util.executeCommand(ev.currentTarget, context);
|
||||||
},
|
},
|
||||||
|
|
||||||
getHeading: function() {
|
getHeading: function() {
|
||||||
|
@ -7867,11 +7979,18 @@ function getManTemplateData(command, context) {
|
||||||
command: command,
|
command: command,
|
||||||
|
|
||||||
onclick: function(ev) {
|
onclick: function(ev) {
|
||||||
updateCommand(ev.currentTarget, context);
|
util.updateCommand(ev.currentTarget, context);
|
||||||
},
|
},
|
||||||
|
|
||||||
ondblclick: function(ev) {
|
ondblclick: function(ev) {
|
||||||
executeCommand(ev.currentTarget, context);
|
util.executeCommand(ev.currentTarget, context);
|
||||||
|
},
|
||||||
|
|
||||||
|
describe: function(item, element) {
|
||||||
|
var text = item.manual || item.description;
|
||||||
|
var parent = element.ownerDocument.createElement('div');
|
||||||
|
util.setContents(parent, text);
|
||||||
|
return parent.childNodes;
|
||||||
},
|
},
|
||||||
|
|
||||||
getTypeDescription: function(param) {
|
getTypeDescription: function(param) {
|
||||||
|
@ -7911,8 +8030,8 @@ define("text!gcli/commands/help_man.html", [], "\n" +
|
||||||
"\n" +
|
"\n" +
|
||||||
" <h4 class=\"gcli-help-header\">\n" +
|
" <h4 class=\"gcli-help-header\">\n" +
|
||||||
" ${l10n.helpManSynopsis}:\n" +
|
" ${l10n.helpManSynopsis}:\n" +
|
||||||
" <span class=\"gcli-help-synopsis\" onclick=\"${onclick}\">\n" +
|
" <span class=\"gcli-out-shortcut\" onclick=\"${onclick}\" data-command=\"${command.name}\">\n" +
|
||||||
" <span class=\"gcli-help-command\">${command.name}</span>\n" +
|
" ${command.name}\n" +
|
||||||
" <span foreach=\"param in ${command.params}\">\n" +
|
" <span foreach=\"param in ${command.params}\">\n" +
|
||||||
" ${param.defaultValue !== undefined ? '[' + param.name + ']' : param.name}\n" +
|
" ${param.defaultValue !== undefined ? '[' + param.name + ']' : param.name}\n" +
|
||||||
" </span>\n" +
|
" </span>\n" +
|
||||||
|
@ -7921,9 +8040,7 @@ define("text!gcli/commands/help_man.html", [], "\n" +
|
||||||
"\n" +
|
"\n" +
|
||||||
" <h4 class=\"gcli-help-header\">${l10n.helpManDescription}:</h4>\n" +
|
" <h4 class=\"gcli-help-header\">${l10n.helpManDescription}:</h4>\n" +
|
||||||
"\n" +
|
"\n" +
|
||||||
" <p class=\"gcli-help-description\">\n" +
|
" <p class=\"gcli-help-description\">${describe(command, __element)}</p>\n" +
|
||||||
" ${command.manual || command.description}\n" +
|
|
||||||
" </p>\n" +
|
|
||||||
"\n" +
|
"\n" +
|
||||||
" <div if=\"${command.exec}\">\n" +
|
" <div if=\"${command.exec}\">\n" +
|
||||||
" <h4 class=\"gcli-help-header\">${l10n.helpManParameters}:</h4>\n" +
|
" <h4 class=\"gcli-help-header\">${l10n.helpManParameters}:</h4>\n" +
|
||||||
|
@ -7931,9 +8048,9 @@ define("text!gcli/commands/help_man.html", [], "\n" +
|
||||||
" <ul class=\"gcli-help-parameter\">\n" +
|
" <ul class=\"gcli-help-parameter\">\n" +
|
||||||
" <li if=\"${command.params.length === 0}\">${l10n.helpManNone}</li>\n" +
|
" <li if=\"${command.params.length === 0}\">${l10n.helpManNone}</li>\n" +
|
||||||
" <li foreach=\"param in ${command.params}\">\n" +
|
" <li foreach=\"param in ${command.params}\">\n" +
|
||||||
" <tt>${param.name}</tt> ${getTypeDescription(param)}\n" +
|
" ${param.name} <em>${getTypeDescription(param)}</em>\n" +
|
||||||
" <br/>\n" +
|
" <br/>\n" +
|
||||||
" ${param.manual || param.description}\n" +
|
" ${describe(param, __element)}\n" +
|
||||||
" </li>\n" +
|
" </li>\n" +
|
||||||
" </ul>\n" +
|
" </ul>\n" +
|
||||||
" </div>\n" +
|
" </div>\n" +
|
||||||
|
@ -7946,8 +8063,9 @@ define("text!gcli/commands/help_man.html", [], "\n" +
|
||||||
" <li foreach=\"subcommand in ${subcommands}\">\n" +
|
" <li foreach=\"subcommand in ${subcommands}\">\n" +
|
||||||
" <strong>${subcommand.name}</strong>:\n" +
|
" <strong>${subcommand.name}</strong>:\n" +
|
||||||
" ${subcommand.description}\n" +
|
" ${subcommand.description}\n" +
|
||||||
" <span class=\"gcli-help-synopsis\" onclick=\"${onclick}\" ondblclick=\"${ondblclick}\">\n" +
|
" <span class=\"gcli-out-shortcut\" data-command=\"help ${subcommand.name}\"\n" +
|
||||||
" <span class=\"gcli-help-command\">help ${subcommand.name}</span>\n" +
|
" onclick=\"${onclick}\" ondblclick=\"${ondblclick}\">\n" +
|
||||||
|
" help ${subcommand.name}\n" +
|
||||||
" </span>\n" +
|
" </span>\n" +
|
||||||
" </li>\n" +
|
" </li>\n" +
|
||||||
" </ul>\n" +
|
" </ul>\n" +
|
||||||
|
@ -7967,7 +8085,7 @@ define("text!gcli/commands/help_list.html", [], "\n" +
|
||||||
" <td class=\"gcli-help-arrow\">→</td>\n" +
|
" <td class=\"gcli-help-arrow\">→</td>\n" +
|
||||||
" <td>\n" +
|
" <td>\n" +
|
||||||
" ${command.description}\n" +
|
" ${command.description}\n" +
|
||||||
" <span class=\"gcli-out-shortcut gcli-help-command\">help ${command.name}</span>\n" +
|
" <span class=\"gcli-out-shortcut\" data-command=\"help ${command.name}\">help ${command.name}</span>\n" +
|
||||||
" </td>\n" +
|
" </td>\n" +
|
||||||
" </tr>\n" +
|
" </tr>\n" +
|
||||||
" </table>\n" +
|
" </table>\n" +
|
||||||
|
@ -7976,6 +8094,151 @@ define("text!gcli/commands/help_list.html", [], "\n" +
|
||||||
|
|
||||||
define("text!gcli/commands/help.css", [], "");
|
define("text!gcli/commands/help.css", [], "");
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright 2009-2011 Mozilla Foundation and contributors
|
||||||
|
* Licensed under the New BSD license. See LICENSE.txt or:
|
||||||
|
* http://opensource.org/licenses/BSD-3-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
define('gcli/commands/pref', ['require', 'exports', 'module' , 'gcli/canon', 'gcli/l10n', 'gcli/settings', 'text!gcli/commands/pref_set_check.html'], function(require, exports, module) {
|
||||||
|
|
||||||
|
|
||||||
|
var canon = require('gcli/canon');
|
||||||
|
var l10n = require('gcli/l10n');
|
||||||
|
var settings = require('gcli/settings');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Record if the user has clicked on 'Got It!'
|
||||||
|
*/
|
||||||
|
var allowSetSettingSpec = {
|
||||||
|
name: 'allowSet',
|
||||||
|
type: 'boolean',
|
||||||
|
description: l10n.lookup('allowSetDesc'),
|
||||||
|
defaultValue: false
|
||||||
|
};
|
||||||
|
exports.allowSet = undefined;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 'pref' command
|
||||||
|
*/
|
||||||
|
var prefCmdSpec = {
|
||||||
|
name: 'pref',
|
||||||
|
description: l10n.lookup('prefDesc'),
|
||||||
|
manual: l10n.lookup('prefManual')
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 'pref show' command
|
||||||
|
*/
|
||||||
|
var prefShowCmdSpec = {
|
||||||
|
name: 'pref show',
|
||||||
|
description: l10n.lookup('prefShowDesc'),
|
||||||
|
manual: l10n.lookup('prefShowManual'),
|
||||||
|
params: [
|
||||||
|
{
|
||||||
|
name: 'setting',
|
||||||
|
type: 'setting',
|
||||||
|
description: l10n.lookup('prefShowSettingDesc'),
|
||||||
|
manual: l10n.lookup('prefShowSettingManual')
|
||||||
|
}
|
||||||
|
],
|
||||||
|
exec: function Command_prefShow(args, context) {
|
||||||
|
return args.setting.value;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 'pref set' command
|
||||||
|
*/
|
||||||
|
var prefSetCmdSpec = {
|
||||||
|
name: 'pref set',
|
||||||
|
description: l10n.lookup('prefSetDesc'),
|
||||||
|
manual: l10n.lookup('prefSetManual'),
|
||||||
|
params: [
|
||||||
|
{
|
||||||
|
name: 'setting',
|
||||||
|
type: 'setting',
|
||||||
|
description: l10n.lookup('prefSetSettingDesc'),
|
||||||
|
manual: l10n.lookup('prefSetSettingManual')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'value',
|
||||||
|
type: 'settingValue',
|
||||||
|
description: l10n.lookup('prefSetValueDesc'),
|
||||||
|
manual: l10n.lookup('prefSetValueManual')
|
||||||
|
}
|
||||||
|
],
|
||||||
|
exec: function Command_prefSet(args, context) {
|
||||||
|
if (!exports.allowSet.value &&
|
||||||
|
args.setting.name !== exports.allowSet.name) {
|
||||||
|
return context.createView({
|
||||||
|
html: require('text!gcli/commands/pref_set_check.html'),
|
||||||
|
options: { allowEval: true, stack: 'pref_set_check.html' },
|
||||||
|
data: {
|
||||||
|
l10n: l10n.propertyLookup,
|
||||||
|
activate: function() {
|
||||||
|
context.exec('pref set ' + exports.allowSet.name + ' true');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
args.setting.value = args.value;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 'pref reset' command
|
||||||
|
*/
|
||||||
|
var prefResetCmdSpec = {
|
||||||
|
name: 'pref reset',
|
||||||
|
description: l10n.lookup('prefResetDesc'),
|
||||||
|
manual: l10n.lookup('prefResetManual'),
|
||||||
|
params: [
|
||||||
|
{
|
||||||
|
name: 'setting',
|
||||||
|
type: 'setting',
|
||||||
|
description: l10n.lookup('prefResetSettingDesc'),
|
||||||
|
manual: l10n.lookup('prefResetSettingManual')
|
||||||
|
}
|
||||||
|
],
|
||||||
|
exec: function Command_prefReset(args, context) {
|
||||||
|
args.setting.setDefault();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registration and de-registration.
|
||||||
|
*/
|
||||||
|
exports.startup = function() {
|
||||||
|
exports.allowSet = settings.addSetting(allowSetSettingSpec);
|
||||||
|
|
||||||
|
canon.addCommand(prefCmdSpec);
|
||||||
|
canon.addCommand(prefShowCmdSpec);
|
||||||
|
canon.addCommand(prefSetCmdSpec);
|
||||||
|
canon.addCommand(prefResetCmdSpec);
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.shutdown = function() {
|
||||||
|
canon.removeCommand(prefCmdSpec);
|
||||||
|
canon.removeCommand(prefShowCmdSpec);
|
||||||
|
canon.removeCommand(prefSetCmdSpec);
|
||||||
|
canon.removeCommand(prefResetCmdSpec);
|
||||||
|
|
||||||
|
settings.removeSetting(allowSetSettingSpec);
|
||||||
|
exports.allowSet = undefined;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
});
|
||||||
|
define("text!gcli/commands/pref_set_check.html", [], "<div>\n" +
|
||||||
|
" <p><strong>${l10n.prefSetCheckHeading}</strong></p>\n" +
|
||||||
|
" <p>${l10n.prefSetCheckBody}</p>\n" +
|
||||||
|
" <button onclick=\"${activate}\">${l10n.prefSetCheckGo}</button>\n" +
|
||||||
|
"</div>\n" +
|
||||||
|
"");
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright 2009-2011 Mozilla Foundation and contributors
|
* Copyright 2009-2011 Mozilla Foundation and contributors
|
||||||
* Licensed under the New BSD license. See LICENSE.txt or:
|
* Licensed under the New BSD license. See LICENSE.txt or:
|
||||||
|
|
|
@ -1,18 +1,11 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
|
||||||
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"
|
|
||||||
[
|
|
||||||
<!ENTITY % webConsoleDTD SYSTEM "chrome://browser/locale/devtools/webConsole.dtd">
|
|
||||||
%webConsoleDTD;
|
|
||||||
]
|
|
||||||
>
|
|
||||||
|
|
||||||
<!-- This Source Code Form is subject to the terms of the Mozilla Public
|
<!-- 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
|
- License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
|
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
|
||||||
|
|
||||||
|
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
|
|
||||||
<head>
|
<head>
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
|
||||||
<link rel="stylesheet" href="chrome://global/skin/global.css" type="text/css"/>
|
<link rel="stylesheet" href="chrome://global/skin/global.css" type="text/css"/>
|
||||||
|
|
|
@ -1,18 +1,11 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
|
||||||
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"
|
|
||||||
[
|
|
||||||
<!ENTITY % webConsoleDTD SYSTEM "chrome://browser/locale/devtools/webConsole.dtd">
|
|
||||||
%webConsoleDTD;
|
|
||||||
]
|
|
||||||
>
|
|
||||||
|
|
||||||
<!-- This Source Code Form is subject to the terms of the Mozilla Public
|
<!-- 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
|
- License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
|
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
|
||||||
|
|
||||||
|
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
|
|
||||||
<head>
|
<head>
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
|
||||||
<link rel="stylesheet" href="chrome://global/skin/global.css" type="text/css"/>
|
<link rel="stylesheet" href="chrome://global/skin/global.css" type="text/css"/>
|
||||||
|
|
|
@ -17,6 +17,8 @@ _BROWSER_TEST_FILES = \
|
||||||
browser_gcli_commands.js \
|
browser_gcli_commands.js \
|
||||||
browser_gcli_inspect.js \
|
browser_gcli_inspect.js \
|
||||||
browser_gcli_integrate.js \
|
browser_gcli_integrate.js \
|
||||||
|
browser_gcli_pref.js \
|
||||||
|
browser_gcli_settings.js \
|
||||||
browser_gcli_web.js \
|
browser_gcli_web.js \
|
||||||
head.js \
|
head.js \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
|
@ -0,0 +1,414 @@
|
||||||
|
/* Any copyright is dedicated to the Public Domain.
|
||||||
|
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||||
|
|
||||||
|
// Tests that the pref commands work
|
||||||
|
|
||||||
|
let imports = {};
|
||||||
|
|
||||||
|
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm", imports);
|
||||||
|
|
||||||
|
imports.XPCOMUtils.defineLazyGetter(imports, "prefBranch", function() {
|
||||||
|
let prefService = Components.classes["@mozilla.org/preferences-service;1"]
|
||||||
|
.getService(Components.interfaces.nsIPrefService);
|
||||||
|
return prefService.getBranch(null)
|
||||||
|
.QueryInterface(Components.interfaces.nsIPrefBranch2);
|
||||||
|
});
|
||||||
|
|
||||||
|
imports.XPCOMUtils.defineLazyGetter(imports, "supportsString", function() {
|
||||||
|
return Components.classes["@mozilla.org/supports-string;1"]
|
||||||
|
.createInstance(Components.interfaces.nsISupportsString);
|
||||||
|
});
|
||||||
|
|
||||||
|
const TEST_URI = "data:text/html;charset=utf-8,gcli-pref";
|
||||||
|
|
||||||
|
function test() {
|
||||||
|
DeveloperToolbarTest.test(TEST_URI, function(browser, tab) {
|
||||||
|
setup();
|
||||||
|
|
||||||
|
testPrefSetEnable();
|
||||||
|
testPrefStatus();
|
||||||
|
testPrefBoolExec();
|
||||||
|
testPrefNumberExec();
|
||||||
|
testPrefStringExec();
|
||||||
|
testPrefSetDisable();
|
||||||
|
|
||||||
|
shutdown();
|
||||||
|
finish();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
let tiltEnabledOrig = undefined;
|
||||||
|
let tabSizeOrig = undefined;
|
||||||
|
let remoteHostOrig = undefined;
|
||||||
|
|
||||||
|
function setup() {
|
||||||
|
Components.utils.import("resource:///modules/devtools/Require.jsm", imports);
|
||||||
|
imports.settings = imports.require("gcli/settings");
|
||||||
|
|
||||||
|
tiltEnabledOrig = imports.prefBranch.getBoolPref("devtools.tilt.enabled");
|
||||||
|
tabSizeOrig = imports.prefBranch.getIntPref("devtools.editor.tabsize");
|
||||||
|
remoteHostOrig = imports.prefBranch.getComplexValue(
|
||||||
|
"devtools.debugger.remote-host",
|
||||||
|
Components.interfaces.nsISupportsString).data;
|
||||||
|
|
||||||
|
info("originally: devtools.tilt.enabled = " + tiltEnabledOrig);
|
||||||
|
info("originally: devtools.editor.tabsize = " + tabSizeOrig);
|
||||||
|
info("originally: devtools.debugger.remote-host = " + remoteHostOrig);
|
||||||
|
}
|
||||||
|
|
||||||
|
function shutdown() {
|
||||||
|
imports.prefBranch.setBoolPref("devtools.tilt.enabled", tiltEnabledOrig);
|
||||||
|
imports.prefBranch.setIntPref("devtools.editor.tabsize", tabSizeOrig);
|
||||||
|
imports.supportsString.data = remoteHostOrig;
|
||||||
|
imports.prefBranch.setComplexValue("devtools.debugger.remote-host",
|
||||||
|
Components.interfaces.nsISupportsString,
|
||||||
|
imports.supportsString);
|
||||||
|
|
||||||
|
tiltEnabledOrig = undefined;
|
||||||
|
tabSizeOrig = undefined;
|
||||||
|
remoteHostOrig = undefined;
|
||||||
|
|
||||||
|
imports = undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
function testPrefStatus() {
|
||||||
|
DeveloperToolbarTest.checkInputStatus({
|
||||||
|
typed: "pref s",
|
||||||
|
markup: "IIIIVI",
|
||||||
|
status: "ERROR",
|
||||||
|
directTabText: "et"
|
||||||
|
});
|
||||||
|
|
||||||
|
DeveloperToolbarTest.checkInputStatus({
|
||||||
|
typed: "pref show",
|
||||||
|
markup: "VVVVVVVVV",
|
||||||
|
status: "ERROR",
|
||||||
|
emptyParameters: [ " <setting>" ]
|
||||||
|
});
|
||||||
|
|
||||||
|
DeveloperToolbarTest.checkInputStatus({
|
||||||
|
typed: "pref show tempTBo",
|
||||||
|
markup: "VVVVVVVVVVEEEEEEE",
|
||||||
|
status: "ERROR",
|
||||||
|
emptyParameters: [ ]
|
||||||
|
});
|
||||||
|
|
||||||
|
DeveloperToolbarTest.checkInputStatus({
|
||||||
|
typed: "pref show devtools.toolbar.ena",
|
||||||
|
markup: "VVVVVVVVVVVVVVVVVVVVVVVVVVVVVV",
|
||||||
|
directTabText: "bled",
|
||||||
|
status: "ERROR",
|
||||||
|
emptyParameters: [ ]
|
||||||
|
});
|
||||||
|
|
||||||
|
DeveloperToolbarTest.checkInputStatus({
|
||||||
|
typed: "pref show hideIntro",
|
||||||
|
markup: "VVVVVVVVVVVVVVVVVVV",
|
||||||
|
directTabText: "",
|
||||||
|
arrowTabText: "devtools.gcli.hideIntro",
|
||||||
|
status: "ERROR",
|
||||||
|
emptyParameters: [ ]
|
||||||
|
});
|
||||||
|
|
||||||
|
DeveloperToolbarTest.checkInputStatus({
|
||||||
|
typed: "pref show devtools.toolbar.enabled",
|
||||||
|
markup: "VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV",
|
||||||
|
status: "VALID",
|
||||||
|
emptyParameters: [ ]
|
||||||
|
});
|
||||||
|
|
||||||
|
DeveloperToolbarTest.checkInputStatus({
|
||||||
|
typed: "pref show devtools.tilt.enabled 4",
|
||||||
|
markup: "VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVE",
|
||||||
|
directTabText: "",
|
||||||
|
status: "ERROR",
|
||||||
|
emptyParameters: [ ]
|
||||||
|
});
|
||||||
|
|
||||||
|
DeveloperToolbarTest.checkInputStatus({
|
||||||
|
typed: "pref show devtools.tilt.enabled",
|
||||||
|
markup: "VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV",
|
||||||
|
status: "VALID",
|
||||||
|
emptyParameters: [ ]
|
||||||
|
});
|
||||||
|
|
||||||
|
DeveloperToolbarTest.checkInputStatus({
|
||||||
|
typed: "pref reset devtools.tilt.enabled",
|
||||||
|
markup: "VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV",
|
||||||
|
status: "VALID",
|
||||||
|
emptyParameters: [ ]
|
||||||
|
});
|
||||||
|
|
||||||
|
DeveloperToolbarTest.checkInputStatus({
|
||||||
|
typed: "pref set devtools.tilt.enabled 4",
|
||||||
|
markup: "VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVE",
|
||||||
|
status: "ERROR",
|
||||||
|
emptyParameters: [ ]
|
||||||
|
});
|
||||||
|
|
||||||
|
DeveloperToolbarTest.checkInputStatus({
|
||||||
|
typed: "pref set devtools.editor.tabsize 4",
|
||||||
|
markup: "VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV",
|
||||||
|
status: "VALID",
|
||||||
|
emptyParameters: [ ]
|
||||||
|
});
|
||||||
|
|
||||||
|
DeveloperToolbarTest.checkInputStatus({
|
||||||
|
typed: "pref list",
|
||||||
|
markup: "EEEEVEEEE",
|
||||||
|
status: "ERROR",
|
||||||
|
emptyParameters: [ ]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function testPrefSetEnable() {
|
||||||
|
DeveloperToolbarTest.exec({
|
||||||
|
typed: "pref set devtools.editor.tabsize 9",
|
||||||
|
args: {
|
||||||
|
setting: imports.settings.getSetting("devtools.editor.tabsize"),
|
||||||
|
value: 9
|
||||||
|
},
|
||||||
|
completed: true,
|
||||||
|
outputMatch: [ /void your warranty/, /I promise/ ],
|
||||||
|
});
|
||||||
|
|
||||||
|
is(imports.prefBranch.getIntPref("devtools.editor.tabsize"),
|
||||||
|
tabSizeOrig,
|
||||||
|
"devtools.editor.tabsize is unchanged");
|
||||||
|
|
||||||
|
DeveloperToolbarTest.exec({
|
||||||
|
typed: "pref set devtools.gcli.allowSet true",
|
||||||
|
args: {
|
||||||
|
setting: imports.settings.getSetting("devtools.gcli.allowSet"),
|
||||||
|
value: true
|
||||||
|
},
|
||||||
|
completed: true,
|
||||||
|
blankOutput: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
is(imports.prefBranch.getBoolPref("devtools.gcli.allowSet"), true,
|
||||||
|
"devtools.gcli.allowSet is true");
|
||||||
|
|
||||||
|
DeveloperToolbarTest.exec({
|
||||||
|
typed: "pref set devtools.editor.tabsize 10",
|
||||||
|
args: {
|
||||||
|
setting: imports.settings.getSetting("devtools.editor.tabsize"),
|
||||||
|
value: 10
|
||||||
|
},
|
||||||
|
completed: true,
|
||||||
|
blankOutput: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
is(imports.prefBranch.getIntPref("devtools.editor.tabsize"),
|
||||||
|
10,
|
||||||
|
"devtools.editor.tabsize is 10");
|
||||||
|
}
|
||||||
|
|
||||||
|
function testPrefBoolExec() {
|
||||||
|
DeveloperToolbarTest.exec({
|
||||||
|
typed: "pref show devtools.tilt.enabled",
|
||||||
|
args: {
|
||||||
|
setting: imports.settings.getSetting("devtools.tilt.enabled")
|
||||||
|
},
|
||||||
|
completed: true,
|
||||||
|
outputMatch: new RegExp("^" + tiltEnabledOrig + "$"),
|
||||||
|
});
|
||||||
|
|
||||||
|
DeveloperToolbarTest.exec({
|
||||||
|
typed: "pref set devtools.tilt.enabled true",
|
||||||
|
args: {
|
||||||
|
setting: imports.settings.getSetting("devtools.tilt.enabled"),
|
||||||
|
value: true
|
||||||
|
},
|
||||||
|
completed: true,
|
||||||
|
blankOutput: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
is(imports.prefBranch.getBoolPref("devtools.tilt.enabled"), true,
|
||||||
|
"devtools.tilt.enabled is true");
|
||||||
|
|
||||||
|
DeveloperToolbarTest.exec({
|
||||||
|
typed: "pref show devtools.tilt.enabled",
|
||||||
|
args: {
|
||||||
|
setting: imports.settings.getSetting("devtools.tilt.enabled")
|
||||||
|
},
|
||||||
|
completed: true,
|
||||||
|
outputMatch: new RegExp("^true$"),
|
||||||
|
});
|
||||||
|
|
||||||
|
DeveloperToolbarTest.exec({
|
||||||
|
typed: "pref set devtools.tilt.enabled false",
|
||||||
|
args: {
|
||||||
|
setting: imports.settings.getSetting("devtools.tilt.enabled"),
|
||||||
|
value: false
|
||||||
|
},
|
||||||
|
completed: true,
|
||||||
|
blankOutput: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
DeveloperToolbarTest.exec({
|
||||||
|
typed: "pref show devtools.tilt.enabled",
|
||||||
|
args: {
|
||||||
|
setting: imports.settings.getSetting("devtools.tilt.enabled")
|
||||||
|
},
|
||||||
|
completed: true,
|
||||||
|
outputMatch: new RegExp("^false$"),
|
||||||
|
});
|
||||||
|
|
||||||
|
is(imports.prefBranch.getBoolPref("devtools.tilt.enabled"), false,
|
||||||
|
"devtools.tilt.enabled is false");
|
||||||
|
}
|
||||||
|
|
||||||
|
function testPrefNumberExec() {
|
||||||
|
DeveloperToolbarTest.exec({
|
||||||
|
typed: "pref show devtools.editor.tabsize",
|
||||||
|
args: {
|
||||||
|
setting: imports.settings.getSetting("devtools.editor.tabsize")
|
||||||
|
},
|
||||||
|
completed: true,
|
||||||
|
outputMatch: new RegExp("^10$"),
|
||||||
|
});
|
||||||
|
|
||||||
|
DeveloperToolbarTest.exec({
|
||||||
|
typed: "pref set devtools.editor.tabsize 20",
|
||||||
|
args: {
|
||||||
|
setting: imports.settings.getSetting("devtools.editor.tabsize"),
|
||||||
|
value: 20
|
||||||
|
},
|
||||||
|
completed: true,
|
||||||
|
blankOutput: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
DeveloperToolbarTest.exec({
|
||||||
|
typed: "pref show devtools.editor.tabsize",
|
||||||
|
args: {
|
||||||
|
setting: imports.settings.getSetting("devtools.editor.tabsize")
|
||||||
|
},
|
||||||
|
completed: true,
|
||||||
|
outputMatch: new RegExp("^20$"),
|
||||||
|
});
|
||||||
|
|
||||||
|
is(imports.prefBranch.getIntPref("devtools.editor.tabsize"), 20,
|
||||||
|
"devtools.editor.tabsize is 20");
|
||||||
|
|
||||||
|
DeveloperToolbarTest.exec({
|
||||||
|
typed: "pref set devtools.editor.tabsize 1",
|
||||||
|
args: {
|
||||||
|
setting: imports.settings.getSetting("devtools.editor.tabsize"),
|
||||||
|
value: true
|
||||||
|
},
|
||||||
|
completed: true,
|
||||||
|
blankOutput: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
DeveloperToolbarTest.exec({
|
||||||
|
typed: "pref show devtools.editor.tabsize",
|
||||||
|
args: {
|
||||||
|
setting: imports.settings.getSetting("devtools.editor.tabsize")
|
||||||
|
},
|
||||||
|
completed: true,
|
||||||
|
outputMatch: new RegExp("^1$"),
|
||||||
|
});
|
||||||
|
|
||||||
|
is(imports.prefBranch.getIntPref("devtools.editor.tabsize"), 1,
|
||||||
|
"devtools.editor.tabsize is 1");
|
||||||
|
}
|
||||||
|
|
||||||
|
function testPrefStringExec() {
|
||||||
|
DeveloperToolbarTest.exec({
|
||||||
|
typed: "pref show devtools.debugger.remote-host",
|
||||||
|
args: {
|
||||||
|
setting: imports.settings.getSetting("devtools.debugger.remote-host")
|
||||||
|
},
|
||||||
|
completed: true,
|
||||||
|
outputMatch: new RegExp("^" + remoteHostOrig + "$"),
|
||||||
|
});
|
||||||
|
|
||||||
|
DeveloperToolbarTest.exec({
|
||||||
|
typed: "pref set devtools.debugger.remote-host e.com",
|
||||||
|
args: {
|
||||||
|
setting: imports.settings.getSetting("devtools.debugger.remote-host"),
|
||||||
|
value: "e.com"
|
||||||
|
},
|
||||||
|
completed: true,
|
||||||
|
blankOutput: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
DeveloperToolbarTest.exec({
|
||||||
|
typed: "pref show devtools.debugger.remote-host",
|
||||||
|
args: {
|
||||||
|
setting: imports.settings.getSetting("devtools.debugger.remote-host")
|
||||||
|
},
|
||||||
|
completed: true,
|
||||||
|
outputMatch: new RegExp("^e.com$"),
|
||||||
|
});
|
||||||
|
|
||||||
|
var ecom = imports.prefBranch.getComplexValue(
|
||||||
|
"devtools.debugger.remote-host",
|
||||||
|
Components.interfaces.nsISupportsString).data;
|
||||||
|
is(ecom, "e.com", "devtools.debugger.remote-host is e.com");
|
||||||
|
|
||||||
|
DeveloperToolbarTest.exec({
|
||||||
|
typed: "pref set devtools.debugger.remote-host moz.foo",
|
||||||
|
args: {
|
||||||
|
setting: imports.settings.getSetting("devtools.debugger.remote-host"),
|
||||||
|
value: "moz.foo"
|
||||||
|
},
|
||||||
|
completed: true,
|
||||||
|
blankOutput: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
DeveloperToolbarTest.exec({
|
||||||
|
typed: "pref show devtools.debugger.remote-host",
|
||||||
|
args: {
|
||||||
|
setting: imports.settings.getSetting("devtools.debugger.remote-host")
|
||||||
|
},
|
||||||
|
completed: true,
|
||||||
|
outputMatch: new RegExp("^moz.foo$"),
|
||||||
|
});
|
||||||
|
|
||||||
|
var mozfoo = imports.prefBranch.getComplexValue(
|
||||||
|
"devtools.debugger.remote-host",
|
||||||
|
Components.interfaces.nsISupportsString).data;
|
||||||
|
is(mozfoo, "moz.foo", "devtools.debugger.remote-host is moz.foo");
|
||||||
|
}
|
||||||
|
|
||||||
|
function testPrefSetDisable() {
|
||||||
|
DeveloperToolbarTest.exec({
|
||||||
|
typed: "pref set devtools.editor.tabsize 32",
|
||||||
|
args: {
|
||||||
|
setting: imports.settings.getSetting("devtools.editor.tabsize"),
|
||||||
|
value: 32
|
||||||
|
},
|
||||||
|
completed: true,
|
||||||
|
blankOutput: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
is(imports.prefBranch.getIntPref("devtools.editor.tabsize"), 32,
|
||||||
|
"devtools.editor.tabsize is 32");
|
||||||
|
|
||||||
|
DeveloperToolbarTest.exec({
|
||||||
|
typed: "pref reset devtools.gcli.allowSet",
|
||||||
|
args: {
|
||||||
|
setting: imports.settings.getSetting("devtools.gcli.allowSet")
|
||||||
|
},
|
||||||
|
completed: true,
|
||||||
|
blankOutput: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
is(imports.prefBranch.getBoolPref("devtools.gcli.allowSet"), false,
|
||||||
|
"devtools.gcli.allowSet is false");
|
||||||
|
|
||||||
|
DeveloperToolbarTest.exec({
|
||||||
|
typed: "pref set devtools.editor.tabsize 33",
|
||||||
|
args: {
|
||||||
|
setting: imports.settings.getSetting("devtools.editor.tabsize"),
|
||||||
|
value: 33
|
||||||
|
},
|
||||||
|
completed: true,
|
||||||
|
outputMatch: [ /void your warranty/, /I promise/ ],
|
||||||
|
});
|
||||||
|
|
||||||
|
is(imports.prefBranch.getIntPref("devtools.editor.tabsize"), 32,
|
||||||
|
"devtools.editor.tabsize is still 32");
|
||||||
|
}
|
|
@ -0,0 +1,149 @@
|
||||||
|
/* Any copyright is dedicated to the Public Domain.
|
||||||
|
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||||
|
|
||||||
|
// Tests that the pref commands work
|
||||||
|
|
||||||
|
let imports = {};
|
||||||
|
|
||||||
|
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm", imports);
|
||||||
|
|
||||||
|
imports.XPCOMUtils.defineLazyGetter(imports, "prefBranch", function() {
|
||||||
|
let prefService = Components.classes["@mozilla.org/preferences-service;1"]
|
||||||
|
.getService(Components.interfaces.nsIPrefService);
|
||||||
|
return prefService.getBranch(null)
|
||||||
|
.QueryInterface(Components.interfaces.nsIPrefBranch2);
|
||||||
|
});
|
||||||
|
|
||||||
|
imports.XPCOMUtils.defineLazyGetter(imports, "supportsString", function() {
|
||||||
|
return Components.classes["@mozilla.org/supports-string;1"]
|
||||||
|
.createInstance(Components.interfaces.nsISupportsString);
|
||||||
|
});
|
||||||
|
|
||||||
|
const TEST_URI = "data:text/html;charset=utf-8,gcli-settings";
|
||||||
|
|
||||||
|
function test() {
|
||||||
|
DeveloperToolbarTest.test(TEST_URI, function(browser, tab) {
|
||||||
|
setup();
|
||||||
|
|
||||||
|
testSettings();
|
||||||
|
|
||||||
|
shutdown();
|
||||||
|
finish();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
let tiltEnabled = undefined;
|
||||||
|
let tabSize = undefined;
|
||||||
|
let remoteHost = undefined;
|
||||||
|
|
||||||
|
let tiltEnabledOrig = undefined;
|
||||||
|
let tabSizeOrig = undefined;
|
||||||
|
let remoteHostOrig = undefined;
|
||||||
|
|
||||||
|
function setup() {
|
||||||
|
Components.utils.import("resource:///modules/devtools/Require.jsm", imports);
|
||||||
|
imports.settings = imports.require("gcli/settings");
|
||||||
|
|
||||||
|
tiltEnabled = imports.settings.getSetting("devtools.tilt.enabled");
|
||||||
|
tabSize = imports.settings.getSetting("devtools.editor.tabsize");
|
||||||
|
remoteHost = imports.settings.getSetting("devtools.debugger.remote-host");
|
||||||
|
|
||||||
|
tiltEnabledOrig = imports.prefBranch.getBoolPref("devtools.tilt.enabled");
|
||||||
|
tabSizeOrig = imports.prefBranch.getIntPref("devtools.editor.tabsize");
|
||||||
|
remoteHostOrig = imports.prefBranch.getComplexValue(
|
||||||
|
"devtools.debugger.remote-host",
|
||||||
|
Components.interfaces.nsISupportsString).data;
|
||||||
|
|
||||||
|
info("originally: devtools.tilt.enabled = " + tiltEnabledOrig);
|
||||||
|
info("originally: devtools.editor.tabsize = " + tabSizeOrig);
|
||||||
|
info("originally: devtools.debugger.remote-host = " + remoteHostOrig);
|
||||||
|
}
|
||||||
|
|
||||||
|
function shutdown() {
|
||||||
|
imports.prefBranch.setBoolPref("devtools.tilt.enabled", tiltEnabledOrig);
|
||||||
|
imports.prefBranch.setIntPref("devtools.editor.tabsize", tabSizeOrig);
|
||||||
|
imports.supportsString.data = remoteHostOrig;
|
||||||
|
imports.prefBranch.setComplexValue("devtools.debugger.remote-host",
|
||||||
|
Components.interfaces.nsISupportsString,
|
||||||
|
imports.supportsString);
|
||||||
|
|
||||||
|
tiltEnabled = undefined;
|
||||||
|
tabSize = undefined;
|
||||||
|
remoteHost = undefined;
|
||||||
|
|
||||||
|
tiltEnabledOrig = undefined;
|
||||||
|
tabSizeOrig = undefined;
|
||||||
|
remoteHostOrig = undefined;
|
||||||
|
|
||||||
|
imports = undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
function testSettings() {
|
||||||
|
is(tiltEnabled.value, tiltEnabledOrig, "tiltEnabled default");
|
||||||
|
is(tabSize.value, tabSizeOrig, "tabSize default");
|
||||||
|
is(remoteHost.value, remoteHostOrig, "remoteHost default");
|
||||||
|
|
||||||
|
tiltEnabled.setDefault();
|
||||||
|
tabSize.setDefault();
|
||||||
|
remoteHost.setDefault();
|
||||||
|
|
||||||
|
let tiltEnabledDefault = tiltEnabled.value;
|
||||||
|
let tabSizeDefault = tabSize.value;
|
||||||
|
let remoteHostDefault = remoteHost.value;
|
||||||
|
|
||||||
|
tiltEnabled.value = false;
|
||||||
|
tabSize.value = 42;
|
||||||
|
remoteHost.value = "example.com"
|
||||||
|
|
||||||
|
is(tiltEnabled.value, false, "tiltEnabled basic");
|
||||||
|
is(tabSize.value, 42, "tabSize basic");
|
||||||
|
is(remoteHost.value, "example.com", "remoteHost basic");
|
||||||
|
|
||||||
|
function tiltEnabledCheck(ev) {
|
||||||
|
is(ev.setting, tiltEnabled, "tiltEnabled event setting");
|
||||||
|
is(ev.value, true, "tiltEnabled event value");
|
||||||
|
is(ev.setting.value, true, "tiltEnabled event setting value");
|
||||||
|
}
|
||||||
|
tiltEnabled.onChange.add(tiltEnabledCheck);
|
||||||
|
tiltEnabled.value = true;
|
||||||
|
is(tiltEnabled.value, true, "tiltEnabled change");
|
||||||
|
|
||||||
|
function tabSizeCheck(ev) {
|
||||||
|
is(ev.setting, tabSize, "tabSize event setting");
|
||||||
|
is(ev.value, 1, "tabSize event value");
|
||||||
|
is(ev.setting.value, 1, "tabSize event setting value");
|
||||||
|
}
|
||||||
|
tabSize.onChange.add(tabSizeCheck);
|
||||||
|
tabSize.value = 1;
|
||||||
|
is(tabSize.value, 1, "tabSize change");
|
||||||
|
|
||||||
|
function remoteHostCheck(ev) {
|
||||||
|
is(ev.setting, remoteHost, "remoteHost event setting");
|
||||||
|
is(ev.value, "y.com", "remoteHost event value");
|
||||||
|
is(ev.setting.value, "y.com", "remoteHost event setting value");
|
||||||
|
}
|
||||||
|
remoteHost.onChange.add(remoteHostCheck);
|
||||||
|
remoteHost.value = "y.com";
|
||||||
|
is(remoteHost.value, "y.com", "remoteHost change");
|
||||||
|
|
||||||
|
tiltEnabled.onChange.remove(tiltEnabledCheck);
|
||||||
|
tabSize.onChange.remove(tabSizeCheck);
|
||||||
|
remoteHost.onChange.remove(remoteHostCheck);
|
||||||
|
|
||||||
|
function remoteHostReCheck(ev) {
|
||||||
|
is(ev.setting, remoteHost, "remoteHost event reset");
|
||||||
|
is(ev.value, null, "remoteHost event revalue");
|
||||||
|
is(ev.setting.value, null, "remoteHost event setting revalue");
|
||||||
|
}
|
||||||
|
remoteHost.onChange.add(remoteHostReCheck);
|
||||||
|
|
||||||
|
tiltEnabled.setDefault();
|
||||||
|
tabSize.setDefault();
|
||||||
|
remoteHost.setDefault();
|
||||||
|
|
||||||
|
remoteHost.onChange.remove(remoteHostReCheck);
|
||||||
|
|
||||||
|
is(tiltEnabled.value, tiltEnabledDefault, "tiltEnabled reset");
|
||||||
|
is(tabSize.value, tabSizeDefault, "tabSize reset");
|
||||||
|
is(remoteHost.value, remoteHostDefault, "remoteHost reset");
|
||||||
|
}
|
|
@ -156,10 +156,11 @@ define('gclitest/suite', ['require', 'exports', 'module' , 'gcli/index', 'test/e
|
||||||
* http://opensource.org/licenses/BSD-3-Clause
|
* http://opensource.org/licenses/BSD-3-Clause
|
||||||
*/
|
*/
|
||||||
|
|
||||||
define('test/examiner', ['require', 'exports', 'module' , 'test/assert'], function(require, exports, module) {
|
define('test/examiner', ['require', 'exports', 'module' , 'test/assert', 'test/status'], function(require, exports, module) {
|
||||||
var examiner = exports;
|
var examiner = exports;
|
||||||
|
|
||||||
var assert = require('test/assert');
|
var assert = require('test/assert');
|
||||||
|
var stati = require('test/status').stati;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test harness data
|
* Test harness data
|
||||||
|
@ -171,14 +172,6 @@ examiner.suites = {};
|
||||||
*/
|
*/
|
||||||
var delay = 10;
|
var delay = 10;
|
||||||
|
|
||||||
var stati = {
|
|
||||||
notrun: { index: 0, name: 'Skipped' },
|
|
||||||
executing: { index: 1, name: 'Executing' },
|
|
||||||
asynchronous: { index: 2, name: 'Waiting' },
|
|
||||||
pass: { index: 3, name: 'Pass' },
|
|
||||||
fail: { index: 4, name: 'Fail' }
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a test suite. Generally used like:
|
* Add a test suite. Generally used like:
|
||||||
* test.addSuite('foo', require('path/to/foo'));
|
* test.addSuite('foo', require('path/to/foo'));
|
||||||
|
@ -580,6 +573,28 @@ define('test/assert', ['require', 'exports', 'module' ], function(require, expor
|
||||||
* http://opensource.org/licenses/BSD-3-Clause
|
* http://opensource.org/licenses/BSD-3-Clause
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
define('test/status', ['require', 'exports', 'module' ], function(require, exports, module) {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This should really be inside assert.js, however that is over-ridden by
|
||||||
|
* a custom assert.js for mozilla, so we keep it separate to avoid
|
||||||
|
* duplicating it in 2 places.
|
||||||
|
*/
|
||||||
|
exports.stati = {
|
||||||
|
notrun: { index: 0, name: 'Skipped' },
|
||||||
|
executing: { index: 1, name: 'Executing' },
|
||||||
|
asynchronous: { index: 2, name: 'Waiting' },
|
||||||
|
pass: { index: 3, name: 'Pass' },
|
||||||
|
fail: { index: 4, name: 'Fail' }
|
||||||
|
};
|
||||||
|
|
||||||
|
});
|
||||||
|
/*
|
||||||
|
* Copyright 2009-2011 Mozilla Foundation and contributors
|
||||||
|
* Licensed under the New BSD license. See LICENSE.txt or:
|
||||||
|
* http://opensource.org/licenses/BSD-3-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
define('gclitest/testCanon', ['require', 'exports', 'module' , 'gclitest/helpers', 'gcli/canon', 'test/assert'], function(require, exports, module) {
|
define('gclitest/testCanon', ['require', 'exports', 'module' , 'gclitest/helpers', 'gcli/canon', 'test/assert'], function(require, exports, module) {
|
||||||
|
|
||||||
var helpers = require('gclitest/helpers');
|
var helpers = require('gclitest/helpers');
|
||||||
|
@ -657,6 +672,14 @@ define('gclitest/testCanon', ['require', 'exports', 'module' , 'gclitest/helpers
|
||||||
status: 'ERROR'
|
status: 'ERROR'
|
||||||
});
|
});
|
||||||
|
|
||||||
|
canon.removeCommand({ name: 'nonexistant' });
|
||||||
|
test.is(canon.getCommands().length, startCount, 'nonexistant1 command success');
|
||||||
|
test.is(events, 5, 'nonexistant1 event');
|
||||||
|
|
||||||
|
canon.removeCommand('nonexistant');
|
||||||
|
test.is(canon.getCommands().length, startCount, 'nonexistant2 command success');
|
||||||
|
test.is(events, 5, 'nonexistant2 event');
|
||||||
|
|
||||||
canon.onCanonChange.remove(canonChange);
|
canon.onCanonChange.remove(canonChange);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -2215,8 +2238,7 @@ define('gclitest/testIntro', ['require', 'exports', 'module' , 'gclitest/helpers
|
||||||
typed: 'intro',
|
typed: 'intro',
|
||||||
args: { },
|
args: { },
|
||||||
outputMatch: [
|
outputMatch: [
|
||||||
/graphical\s*command\s*line/,
|
/command\s*line/,
|
||||||
/GCLI/,
|
|
||||||
/help/,
|
/help/,
|
||||||
/F1/,
|
/F1/,
|
||||||
/Escape/
|
/Escape/
|
||||||
|
@ -2610,9 +2632,69 @@ exports.shutdown = function(options) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
exports.testPrefShowStatus = function(options) {
|
||||||
|
if (options.isFirefox) {
|
||||||
|
test.log('Skipping testPrefShowStatus in Firefox.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
helpers.status(options, {
|
||||||
|
typed: 'pref s',
|
||||||
|
markup: 'IIIIVI',
|
||||||
|
status: 'ERROR',
|
||||||
|
directTabText: 'et'
|
||||||
|
});
|
||||||
|
|
||||||
|
helpers.status(options, {
|
||||||
|
typed: 'pref show',
|
||||||
|
markup: 'VVVVVVVVV',
|
||||||
|
status: 'ERROR',
|
||||||
|
emptyParameters: [ ' <setting>' ]
|
||||||
|
});
|
||||||
|
|
||||||
|
helpers.status(options, {
|
||||||
|
typed: 'pref show ',
|
||||||
|
markup: 'VVVVVVVVVV',
|
||||||
|
status: 'ERROR',
|
||||||
|
emptyParameters: [ ]
|
||||||
|
});
|
||||||
|
|
||||||
|
helpers.status(options, {
|
||||||
|
typed: 'pref show tempTBo',
|
||||||
|
markup: 'VVVVVVVVVVIIIIIII',
|
||||||
|
directTabText: 'ol',
|
||||||
|
status: 'ERROR',
|
||||||
|
emptyParameters: [ ]
|
||||||
|
});
|
||||||
|
|
||||||
|
helpers.status(options, {
|
||||||
|
typed: 'pref show tempTBool',
|
||||||
|
markup: 'VVVVVVVVVVVVVVVVVVV',
|
||||||
|
directTabText: '',
|
||||||
|
status: 'VALID',
|
||||||
|
emptyParameters: [ ]
|
||||||
|
});
|
||||||
|
|
||||||
|
helpers.status(options, {
|
||||||
|
typed: 'pref show tempTBool 4',
|
||||||
|
markup: 'VVVVVVVVVVVVVVVVVVVVE',
|
||||||
|
directTabText: '',
|
||||||
|
status: 'ERROR',
|
||||||
|
emptyParameters: [ ]
|
||||||
|
});
|
||||||
|
|
||||||
|
helpers.status(options, {
|
||||||
|
typed: 'pref show tempNumber 4',
|
||||||
|
markup: 'VVVVVVVVVVVVVVVVVVVVVE',
|
||||||
|
directTabText: '',
|
||||||
|
status: 'ERROR',
|
||||||
|
emptyParameters: [ ]
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
exports.testPrefSetStatus = function(options) {
|
exports.testPrefSetStatus = function(options) {
|
||||||
if (options.isFirefox) {
|
if (options.isFirefox) {
|
||||||
test.log('Skipping testPref in Firefox.');
|
test.log('Skipping testPrefSetStatus in Firefox.');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2643,13 +2725,6 @@ exports.testPrefSetStatus = function(options) {
|
||||||
emptyParameters: [ ' <value>' ]
|
emptyParameters: [ ' <value>' ]
|
||||||
});
|
});
|
||||||
|
|
||||||
helpers.status(options, {
|
|
||||||
typed: 'pref set ',
|
|
||||||
markup: 'VVVVVVVVV',
|
|
||||||
status: 'ERROR',
|
|
||||||
emptyParameters: [ ' <value>' ]
|
|
||||||
});
|
|
||||||
|
|
||||||
helpers.status(options, {
|
helpers.status(options, {
|
||||||
typed: 'pref set tempTBo',
|
typed: 'pref set tempTBo',
|
||||||
markup: 'VVVVVVVVVIIIIIII',
|
markup: 'VVVVVVVVVIIIIIII',
|
||||||
|
@ -2677,7 +2752,7 @@ exports.testPrefSetStatus = function(options) {
|
||||||
|
|
||||||
exports.testPrefExec = function(options) {
|
exports.testPrefExec = function(options) {
|
||||||
if (options.isFirefox) {
|
if (options.isFirefox) {
|
||||||
test.log('Skipping testPref in Firefox.');
|
test.log('Skipping testPrefExec in Firefox.');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2738,313 +2813,6 @@ exports.testPrefExec = function(options) {
|
||||||
* http://opensource.org/licenses/BSD-3-Clause
|
* http://opensource.org/licenses/BSD-3-Clause
|
||||||
*/
|
*/
|
||||||
|
|
||||||
define('gcli/commands/pref', ['require', 'exports', 'module' , 'gcli/index', 'gcli/l10n', 'gcli/util', 'gcli/settings', 'gcli/promise', 'text!gcli/commands/pref_list_outer.html', 'text!gcli/commands/pref_list.css', 'text!gcli/commands/pref_set_check.html', 'text!gcli/commands/pref_list_inner.html'], function(require, exports, module) {
|
|
||||||
|
|
||||||
|
|
||||||
var gcli = require('gcli/index');
|
|
||||||
var l10n = require('gcli/l10n');
|
|
||||||
var util = require('gcli/util');
|
|
||||||
var settings = require('gcli/settings');
|
|
||||||
var Promise = require('gcli/promise').Promise;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Record if the user has clicked on 'Got It!'
|
|
||||||
*/
|
|
||||||
var allowSetSettingSpec = {
|
|
||||||
name: 'allowSet',
|
|
||||||
type: 'boolean',
|
|
||||||
description: l10n.lookup('allowSetDesc'),
|
|
||||||
defaultValue: false
|
|
||||||
};
|
|
||||||
exports.allowSet = undefined;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 'pref' command
|
|
||||||
*/
|
|
||||||
var prefCmdSpec = {
|
|
||||||
name: 'pref',
|
|
||||||
description: l10n.lookup('prefDesc'),
|
|
||||||
manual: l10n.lookup('prefManual')
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 'pref list' command
|
|
||||||
*/
|
|
||||||
var prefListCmdSpec = {
|
|
||||||
name: 'pref list',
|
|
||||||
description: l10n.lookup('prefListDesc'),
|
|
||||||
manual: l10n.lookup('prefListManual'),
|
|
||||||
params: [
|
|
||||||
{
|
|
||||||
name: 'search',
|
|
||||||
type: 'string',
|
|
||||||
defaultValue: null,
|
|
||||||
description: l10n.lookup('prefListSearchDesc'),
|
|
||||||
manual: l10n.lookup('prefListSearchManual')
|
|
||||||
}
|
|
||||||
],
|
|
||||||
exec: function Command_prefList(args, context) {
|
|
||||||
return context.createView({
|
|
||||||
html: require('text!gcli/commands/pref_list_outer.html'),
|
|
||||||
data: new PrefList(args, context),
|
|
||||||
options: {
|
|
||||||
blankNullUndefined: true,
|
|
||||||
allowEval: true,
|
|
||||||
stack: 'pref_list_outer.html'
|
|
||||||
},
|
|
||||||
css: require('text!gcli/commands/pref_list.css'),
|
|
||||||
cssId: 'gcli-pref-list'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 'pref set' command
|
|
||||||
*/
|
|
||||||
var prefSetCmdSpec = {
|
|
||||||
name: 'pref set',
|
|
||||||
description: l10n.lookup('prefSetDesc'),
|
|
||||||
manual: l10n.lookup('prefSetManual'),
|
|
||||||
params: [
|
|
||||||
{
|
|
||||||
name: 'setting',
|
|
||||||
type: 'setting',
|
|
||||||
description: l10n.lookup('prefSetSettingDesc'),
|
|
||||||
manual: l10n.lookup('prefSetSettingManual')
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'value',
|
|
||||||
type: 'settingValue',
|
|
||||||
description: l10n.lookup('prefSetValueDesc'),
|
|
||||||
manual: l10n.lookup('prefSetValueManual')
|
|
||||||
}
|
|
||||||
],
|
|
||||||
exec: function Command_prefSet(args, context) {
|
|
||||||
if (!exports.allowSet.value &&
|
|
||||||
args.setting.name !== exports.allowSet.name) {
|
|
||||||
return context.createView({
|
|
||||||
html: require('text!gcli/commands/pref_set_check.html'),
|
|
||||||
options: { allowEval: true, stack: 'pref_set_check.html' },
|
|
||||||
data: {
|
|
||||||
l10n: l10n.propertyLookup,
|
|
||||||
activate: function() {
|
|
||||||
context.exec('pref set allowSet true');
|
|
||||||
}
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
args.setting.value = args.value;
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 'pref reset' command
|
|
||||||
*/
|
|
||||||
var prefResetCmdSpec = {
|
|
||||||
name: 'pref reset',
|
|
||||||
description: l10n.lookup('prefResetDesc'),
|
|
||||||
manual: l10n.lookup('prefResetManual'),
|
|
||||||
params: [
|
|
||||||
{
|
|
||||||
name: 'setting',
|
|
||||||
type: 'setting',
|
|
||||||
description: l10n.lookup('prefResetSettingDesc'),
|
|
||||||
manual: l10n.lookup('prefResetSettingManual')
|
|
||||||
}
|
|
||||||
],
|
|
||||||
exec: function Command_prefReset(args, context) {
|
|
||||||
args.setting.setDefault();
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Registration and de-registration.
|
|
||||||
*/
|
|
||||||
exports.startup = function() {
|
|
||||||
exports.allowSet = settings.addSetting(allowSetSettingSpec);
|
|
||||||
|
|
||||||
gcli.addCommand(prefCmdSpec);
|
|
||||||
gcli.addCommand(prefListCmdSpec);
|
|
||||||
gcli.addCommand(prefSetCmdSpec);
|
|
||||||
gcli.addCommand(prefResetCmdSpec);
|
|
||||||
};
|
|
||||||
|
|
||||||
exports.shutdown = function() {
|
|
||||||
gcli.removeCommand(prefCmdSpec);
|
|
||||||
gcli.removeCommand(prefListCmdSpec);
|
|
||||||
gcli.removeCommand(prefSetCmdSpec);
|
|
||||||
gcli.removeCommand(prefResetCmdSpec);
|
|
||||||
|
|
||||||
settings.removeSetting(allowSetSettingSpec);
|
|
||||||
exports.allowSet = undefined;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A manager for our version of about:config
|
|
||||||
*/
|
|
||||||
function PrefList(args, context) {
|
|
||||||
this.search = args.search;
|
|
||||||
this.context = context;
|
|
||||||
this.url = util.createUrlLookup(module);
|
|
||||||
this.edit = this.url('pref_list_edit.png');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
PrefList.prototype.onLoad = function(element) {
|
|
||||||
var table = element.querySelector('.gcli-pref-list-table');
|
|
||||||
this.updateTable(table);
|
|
||||||
return '';
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Forward localization lookups
|
|
||||||
*/
|
|
||||||
PrefList.prototype.l10n = l10n.propertyLookup;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called from the template onkeyup for the filter element
|
|
||||||
*/
|
|
||||||
PrefList.prototype.updateTable = function(table) {
|
|
||||||
util.clearElement(table);
|
|
||||||
var view = this.context.createView({
|
|
||||||
html: require('text!gcli/commands/pref_list_inner.html'),
|
|
||||||
options: { blankNullUndefined: true, stack: 'pref_list_inner.html' },
|
|
||||||
data: this
|
|
||||||
});
|
|
||||||
var child = view.toDom(table.ownerDocument);
|
|
||||||
util.setContents(table, child);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Which preferences match the filter?
|
|
||||||
*/
|
|
||||||
Object.defineProperty(PrefList.prototype, 'preferences', {
|
|
||||||
get: function() {
|
|
||||||
return settings.getAll(this.search);
|
|
||||||
},
|
|
||||||
enumerable: true
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Which preferences match the filter?
|
|
||||||
*/
|
|
||||||
Object.defineProperty(PrefList.prototype, 'promisePreferences', {
|
|
||||||
get: function() {
|
|
||||||
var promise = new Promise();
|
|
||||||
setTimeout(function() {
|
|
||||||
promise.resolve(settings.getAll(this.search));
|
|
||||||
}.bind(this), 10);
|
|
||||||
return promise;
|
|
||||||
},
|
|
||||||
enumerable: true
|
|
||||||
});
|
|
||||||
|
|
||||||
PrefList.prototype.onFilterChange = function(ev) {
|
|
||||||
if (ev.target.value !== this.search) {
|
|
||||||
this.search = ev.target.value;
|
|
||||||
|
|
||||||
var root = ev.target.parentNode.parentNode;
|
|
||||||
var table = root.querySelector('.gcli-pref-list-table');
|
|
||||||
this.updateTable(table);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
PrefList.prototype.onSetClick = function(ev) {
|
|
||||||
var typed = ev.currentTarget.getAttribute('data-command');
|
|
||||||
this.context.update(typed);
|
|
||||||
};
|
|
||||||
|
|
||||||
});
|
|
||||||
define("text!gcli/commands/pref_list_outer.html", [], "<div ignore=\"${onLoad(__element)}\">\n" +
|
|
||||||
" <div class=\"gcli-pref-list-filter\">\n" +
|
|
||||||
" ${l10n.prefOutputFilter}:\n" +
|
|
||||||
" <input onKeyUp=\"${onFilterChange}\" value=\"${search}\"/>\n" +
|
|
||||||
" </div>\n" +
|
|
||||||
" <table class=\"gcli-pref-list-table\">\n" +
|
|
||||||
" <colgroup>\n" +
|
|
||||||
" <col class=\"gcli-pref-list-name\"/>\n" +
|
|
||||||
" <col class=\"gcli-pref-list-value\"/>\n" +
|
|
||||||
" </colgroup>\n" +
|
|
||||||
" <tr>\n" +
|
|
||||||
" <th>${l10n.prefOutputName}</th>\n" +
|
|
||||||
" <th>${l10n.prefOutputValue}</th>\n" +
|
|
||||||
" </tr>\n" +
|
|
||||||
" </table>\n" +
|
|
||||||
" <div class=\"gcli-pref-list-scroller\">\n" +
|
|
||||||
" <table class=\"gcli-pref-list-table\" save=\"${table}\">\n" +
|
|
||||||
" </table>\n" +
|
|
||||||
" </div>\n" +
|
|
||||||
"</div>\n" +
|
|
||||||
"");
|
|
||||||
|
|
||||||
define("text!gcli/commands/pref_list.css", [], "\n" +
|
|
||||||
".gcli-pref-list-scroller {\n" +
|
|
||||||
" max-height: 200px;\n" +
|
|
||||||
" overflow-y: auto;\n" +
|
|
||||||
" overflow-x: hidden;\n" +
|
|
||||||
" display: inline-block;\n" +
|
|
||||||
"}\n" +
|
|
||||||
"\n" +
|
|
||||||
".gcli-pref-list-table {\n" +
|
|
||||||
" width: 500px;\n" +
|
|
||||||
" table-layout: fixed;\n" +
|
|
||||||
"}\n" +
|
|
||||||
"\n" +
|
|
||||||
".gcli-pref-list-table tr > th {\n" +
|
|
||||||
" text-align: left;\n" +
|
|
||||||
"}\n" +
|
|
||||||
"\n" +
|
|
||||||
".gcli-pref-list-table tr > td {\n" +
|
|
||||||
" text-overflow: elipsis;\n" +
|
|
||||||
" word-wrap: break-word;\n" +
|
|
||||||
"}\n" +
|
|
||||||
"\n" +
|
|
||||||
".gcli-pref-list-name {\n" +
|
|
||||||
" width: 70%;\n" +
|
|
||||||
"}\n" +
|
|
||||||
"\n" +
|
|
||||||
".gcli-pref-list-command {\n" +
|
|
||||||
" display: none;\n" +
|
|
||||||
"}\n" +
|
|
||||||
"\n" +
|
|
||||||
".gcli-pref-list-row:hover .gcli-pref-list-command {\n" +
|
|
||||||
" display: inline-block;\n" +
|
|
||||||
"}\n" +
|
|
||||||
"");
|
|
||||||
|
|
||||||
define("text!gcli/commands/pref_set_check.html", [], "<div>\n" +
|
|
||||||
" <p><strong>${l10n.prefSetCheckHeading}</strong></p>\n" +
|
|
||||||
" <p>${l10n.prefSetCheckBody}</p>\n" +
|
|
||||||
" <button onclick=\"${activate}\">${l10n.prefSetCheckGo}</button>\n" +
|
|
||||||
"</div>\n" +
|
|
||||||
"");
|
|
||||||
|
|
||||||
define("text!gcli/commands/pref_list_inner.html", [], "<table>\n" +
|
|
||||||
" <colgroup>\n" +
|
|
||||||
" <col class=\"gcli-pref-list-name\"/>\n" +
|
|
||||||
" <col class=\"gcli-pref-list-value\"/>\n" +
|
|
||||||
" </colgroup>\n" +
|
|
||||||
" <tr class=\"gcli-pref-list-row\" foreach=\"preference in ${promisePreferences}\">\n" +
|
|
||||||
" <td>${preference.name}</td>\n" +
|
|
||||||
" <td onclick=\"${onSetClick}\" data-command=\"pref set ${preference.name} \">\n" +
|
|
||||||
" ${preference.value}\n" +
|
|
||||||
" <img class=\"gcli-pref-list-command\" _src=\"${edit}\"/>\n" +
|
|
||||||
" </td>\n" +
|
|
||||||
" </tr>\n" +
|
|
||||||
"</table>\n" +
|
|
||||||
"");
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright 2009-2011 Mozilla Foundation and contributors
|
|
||||||
* Licensed under the New BSD license. See LICENSE.txt or:
|
|
||||||
* http://opensource.org/licenses/BSD-3-Clause
|
|
||||||
*/
|
|
||||||
|
|
||||||
define('gclitest/mockSettings', ['require', 'exports', 'module' , 'gcli/settings'], function(require, exports, module) {
|
define('gclitest/mockSettings', ['require', 'exports', 'module' , 'gcli/settings'], function(require, exports, module) {
|
||||||
|
|
||||||
|
|
||||||
|
@ -4109,6 +3877,7 @@ let testModuleNames = [
|
||||||
'gclitest/suite',
|
'gclitest/suite',
|
||||||
'test/examiner',
|
'test/examiner',
|
||||||
'test/assert',
|
'test/assert',
|
||||||
|
'test/status',
|
||||||
'gclitest/testCanon',
|
'gclitest/testCanon',
|
||||||
'gclitest/helpers',
|
'gclitest/helpers',
|
||||||
'gclitest/testCli',
|
'gclitest/testCli',
|
||||||
|
@ -4122,11 +3891,6 @@ let testModuleNames = [
|
||||||
'gclitest/testJs',
|
'gclitest/testJs',
|
||||||
'gclitest/testKeyboard',
|
'gclitest/testKeyboard',
|
||||||
'gclitest/testPref',
|
'gclitest/testPref',
|
||||||
'gcli/commands/pref',
|
|
||||||
'text!gcli/commands/pref_list_outer.html',
|
|
||||||
'text!gcli/commands/pref_list.css',
|
|
||||||
'text!gcli/commands/pref_set_check.html',
|
|
||||||
'text!gcli/commands/pref_list_inner.html',
|
|
||||||
'gclitest/mockSettings',
|
'gclitest/mockSettings',
|
||||||
'gclitest/testRequire',
|
'gclitest/testRequire',
|
||||||
'gclitest/requirable',
|
'gclitest/requirable',
|
||||||
|
|
|
@ -146,7 +146,8 @@ let DeveloperToolbarTest = {
|
||||||
*
|
*
|
||||||
* // Thing to check
|
* // Thing to check
|
||||||
* args: { message: "hi" }, // Check that the args were understood properly
|
* args: { message: "hi" }, // Check that the args were understood properly
|
||||||
* outputMatch: /^hi$/, // Regex to test against textContent of output
|
* outputMatch: /^hi$/, // RegExp to test against textContent of output
|
||||||
|
* // (can also be array of RegExps)
|
||||||
* blankOutput: true, // Special checks when there is no output
|
* blankOutput: true, // Special checks when there is no output
|
||||||
* });
|
* });
|
||||||
*/
|
*/
|
||||||
|
@ -201,10 +202,21 @@ let DeveloperToolbarTest = {
|
||||||
let displayed = DeveloperToolbar.outputPanel._div.textContent;
|
let displayed = DeveloperToolbar.outputPanel._div.textContent;
|
||||||
|
|
||||||
if (test.outputMatch) {
|
if (test.outputMatch) {
|
||||||
if (!test.outputMatch.test(displayed)) {
|
function doTest(match, against) {
|
||||||
ok(false, "html output for " + typed + " (textContent sent to info)");
|
if (!match.test(against)) {
|
||||||
|
ok(false, "html output for " + typed + " against " + match.source +
|
||||||
|
" (textContent sent to info)");
|
||||||
info("Actual textContent");
|
info("Actual textContent");
|
||||||
info(displayed);
|
info(against);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (Array.isArray(test.outputMatch)) {
|
||||||
|
test.outputMatch.forEach(function(match) {
|
||||||
|
doTest(match, displayed);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
doTest(test.outputMatch, displayed);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -418,9 +418,11 @@ StackFrames.prototype = {
|
||||||
_onFrames: function SF__onFrames() {
|
_onFrames: function SF__onFrames() {
|
||||||
if (!this.activeThread.cachedFrames.length) {
|
if (!this.activeThread.cachedFrames.length) {
|
||||||
DebuggerView.StackFrames.emptyText();
|
DebuggerView.StackFrames.emptyText();
|
||||||
|
DebuggerView.Properties.emptyText();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
DebuggerView.StackFrames.empty();
|
DebuggerView.StackFrames.empty();
|
||||||
|
DebuggerView.Properties.empty();
|
||||||
|
|
||||||
for each (let frame in this.activeThread.cachedFrames) {
|
for each (let frame in this.activeThread.cachedFrames) {
|
||||||
this._addFrame(frame);
|
this._addFrame(frame);
|
||||||
|
@ -451,8 +453,7 @@ StackFrames.prototype = {
|
||||||
_afterFramesCleared: function SF__afterFramesCleared() {
|
_afterFramesCleared: function SF__afterFramesCleared() {
|
||||||
if (!this.activeThread.cachedFrames.length) {
|
if (!this.activeThread.cachedFrames.length) {
|
||||||
DebuggerView.StackFrames.emptyText();
|
DebuggerView.StackFrames.emptyText();
|
||||||
DebuggerView.Properties.localScope.empty();
|
DebuggerView.Properties.emptyText();
|
||||||
DebuggerView.Properties.globalScope.empty();
|
|
||||||
DebuggerController.dispatchEvent("Debugger:AfterFramesCleared");
|
DebuggerController.dispatchEvent("Debugger:AfterFramesCleared");
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -521,39 +522,77 @@ StackFrames.prototype = {
|
||||||
// Start recording any added variables or properties in any scope.
|
// Start recording any added variables or properties in any scope.
|
||||||
DebuggerView.Properties.createHierarchyStore();
|
DebuggerView.Properties.createHierarchyStore();
|
||||||
|
|
||||||
// Display the local variables.
|
// Clear existing scopes and create each one dynamically.
|
||||||
let localScope = DebuggerView.Properties.localScope;
|
DebuggerView.Properties.empty();
|
||||||
localScope.empty();
|
|
||||||
|
|
||||||
// Add "this".
|
if (frame.environment) {
|
||||||
if (frame.this) {
|
let env = frame.environment;
|
||||||
let thisVar = localScope.addVar("this");
|
do {
|
||||||
|
// Construct the scope name.
|
||||||
|
let name = env.type.charAt(0).toUpperCase() + env.type.slice(1);
|
||||||
|
// Call the outermost scope Global.
|
||||||
|
if (!env.parent) {
|
||||||
|
name = L10N.getStr("globalScopeLabel");
|
||||||
|
}
|
||||||
|
let label = L10N.getFormatStr("scopeLabel", [name]);
|
||||||
|
switch (env.type) {
|
||||||
|
case "with":
|
||||||
|
case "object":
|
||||||
|
label += " [" + env.object.class + "]";
|
||||||
|
break;
|
||||||
|
case "function":
|
||||||
|
if (env.functionName) {
|
||||||
|
label += " [" + env.functionName + "]";
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
let scope = DebuggerView.Properties.addScope(label);
|
||||||
|
|
||||||
|
// Add "this" to the innermost scope.
|
||||||
|
if (frame.this && env == frame.environment) {
|
||||||
|
let thisVar = scope.addVar("this");
|
||||||
thisVar.setGrip({
|
thisVar.setGrip({
|
||||||
type: frame.this.type,
|
type: frame.this.type,
|
||||||
class: frame.this.class
|
class: frame.this.class
|
||||||
});
|
});
|
||||||
this._addExpander(thisVar, frame.this);
|
this._addExpander(thisVar, frame.this);
|
||||||
|
// Expand the innermost scope by default.
|
||||||
|
scope.expand(true);
|
||||||
|
scope.addToHierarchy();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (frame.environment) {
|
switch (env.type) {
|
||||||
|
case "with":
|
||||||
|
case "object":
|
||||||
|
let objClient = this.activeThread.pauseGrip(env.object);
|
||||||
|
objClient.getPrototypeAndProperties(function SF_getProps(aResponse) {
|
||||||
|
this._addScopeVariables(aResponse.ownProperties, scope);
|
||||||
|
// Signal that variables have been fetched.
|
||||||
|
DebuggerController.dispatchEvent("Debugger:FetchedVariables");
|
||||||
|
}.bind(this));
|
||||||
|
break;
|
||||||
|
case "block":
|
||||||
|
case "function":
|
||||||
// Add nodes for every argument.
|
// Add nodes for every argument.
|
||||||
let variables = frame.environment.bindings.arguments;
|
let variables = env.bindings.arguments;
|
||||||
for each (let variable in variables) {
|
for each (let variable in variables) {
|
||||||
let name = Object.getOwnPropertyNames(variable)[0];
|
let name = Object.getOwnPropertyNames(variable)[0];
|
||||||
let paramVar = localScope.addVar(name);
|
let paramVar = scope.addVar(name);
|
||||||
let paramVal = variable[name].value;
|
let paramVal = variable[name].value;
|
||||||
paramVar.setGrip(paramVal);
|
paramVar.setGrip(paramVal);
|
||||||
this._addExpander(paramVar, paramVal);
|
this._addExpander(paramVar, paramVal);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add nodes for every other variable in scope.
|
// Add nodes for every other variable in scope.
|
||||||
variables = frame.environment.bindings.variables;
|
this._addScopeVariables(env.bindings.variables, scope);
|
||||||
for (let variable in variables) {
|
break;
|
||||||
let paramVar = localScope.addVar(variable);
|
default:
|
||||||
let paramVal = variables[variable].value;
|
Cu.reportError("Unknown Debugger.Environment type: " + env.type);
|
||||||
paramVar.setGrip(paramVal);
|
break;
|
||||||
this._addExpander(paramVar, paramVal);
|
|
||||||
}
|
}
|
||||||
|
} while (env = env.parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Signal that variables have been fetched.
|
// Signal that variables have been fetched.
|
||||||
|
@ -567,6 +606,31 @@ StackFrames.prototype = {
|
||||||
DebuggerView.Properties.commitHierarchy();
|
DebuggerView.Properties.commitHierarchy();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add nodes for every variable in scope.
|
||||||
|
*
|
||||||
|
* @param object aVariables
|
||||||
|
* The map of names to variables, as specified in the Remote
|
||||||
|
* Debugging Protocol.
|
||||||
|
* @param object aScope
|
||||||
|
* The scope where the nodes will be placed into.
|
||||||
|
*/
|
||||||
|
_addScopeVariables: function SF_addScopeVariables(aVariables, aScope) {
|
||||||
|
// Sort all of the variables before adding them, for better UX.
|
||||||
|
let variables = {};
|
||||||
|
for each (let prop in Object.keys(aVariables).sort()) {
|
||||||
|
variables[prop] = aVariables[prop];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add the sorted variables to the specified scope.
|
||||||
|
for (let variable in variables) {
|
||||||
|
let paramVar = aScope.addVar(variable);
|
||||||
|
let paramVal = variables[variable].value;
|
||||||
|
paramVar.setGrip(paramVal);
|
||||||
|
this._addExpander(paramVar, paramVal);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds an 'onexpand' callback for a variable, lazily handling the addition of
|
* Adds an 'onexpand' callback for a variable, lazily handling the addition of
|
||||||
* new properties.
|
* new properties.
|
||||||
|
|
|
@ -760,12 +760,17 @@ StackFramesView.prototype = {
|
||||||
* Functions handling the properties view.
|
* Functions handling the properties view.
|
||||||
*/
|
*/
|
||||||
function PropertiesView() {
|
function PropertiesView() {
|
||||||
this._addScope = this._addScope.bind(this);
|
this.addScope = this._addScope.bind(this);
|
||||||
this._addVar = this._addVar.bind(this);
|
this._addVar = this._addVar.bind(this);
|
||||||
this._addProperties = this._addProperties.bind(this);
|
this._addProperties = this._addProperties.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
PropertiesView.prototype = {
|
PropertiesView.prototype = {
|
||||||
|
/**
|
||||||
|
* A monotonically-increasing counter, that guarantees the uniqueness of scope
|
||||||
|
* IDs.
|
||||||
|
*/
|
||||||
|
_idCount: 1,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a scope to contain any inspected variables.
|
* Adds a scope to contain any inspected variables.
|
||||||
|
@ -786,8 +791,8 @@ PropertiesView.prototype = {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compute the id of the element if not specified.
|
// Generate a unique id for the element, if not specified.
|
||||||
aId = aId || (aName.toLowerCase().trim().replace(" ", "-") + "-scope");
|
aId = aId || aName.toLowerCase().trim().replace(/\s+/g, "-") + this._idCount++;
|
||||||
|
|
||||||
// Contains generic nodes and functionality.
|
// Contains generic nodes and functionality.
|
||||||
let element = this._createPropertyElement(aName, aId, "scope", this._vars);
|
let element = this._createPropertyElement(aName, aId, "scope", this._vars);
|
||||||
|
@ -796,16 +801,48 @@ PropertiesView.prototype = {
|
||||||
if (!element) {
|
if (!element) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
element._identifier = aName;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see DebuggerView.Properties._addVar
|
* @see DebuggerView.Properties._addVar
|
||||||
*/
|
*/
|
||||||
element.addVar = this._addVar.bind(this, element);
|
element.addVar = this._addVar.bind(this, element);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see DebuggerView.Properties.addScopeToHierarchy
|
||||||
|
*/
|
||||||
|
element.addToHierarchy = this.addScopeToHierarchy.bind(this, element);
|
||||||
|
|
||||||
// Return the element for later use if necessary.
|
// Return the element for later use if necessary.
|
||||||
return element;
|
return element;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes all added scopes in the property container tree.
|
||||||
|
*/
|
||||||
|
empty: function DVP_empty() {
|
||||||
|
while (this._vars.firstChild) {
|
||||||
|
this._vars.removeChild(this._vars.firstChild);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes all elements from the variables container, and adds a child node
|
||||||
|
* with an empty text note attached.
|
||||||
|
*/
|
||||||
|
emptyText: function DVP_emptyText() {
|
||||||
|
// Make sure the container is empty first.
|
||||||
|
this.empty();
|
||||||
|
|
||||||
|
let item = document.createElement("label");
|
||||||
|
|
||||||
|
// The empty node should look grayed out to avoid confusion.
|
||||||
|
item.className = "list-item empty";
|
||||||
|
item.setAttribute("value", L10N.getStr("emptyVariablesText"));
|
||||||
|
|
||||||
|
this._vars.appendChild(item);
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a variable to a specified scope.
|
* Adds a variable to a specified scope.
|
||||||
* If the optional id is not specified, the variable html node will have a
|
* If the optional id is not specified, the variable html node will have a
|
||||||
|
@ -837,6 +874,7 @@ PropertiesView.prototype = {
|
||||||
if (!element) {
|
if (!element) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
element._identifier = aName;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see DebuggerView.Properties._setGrip
|
* @see DebuggerView.Properties._setGrip
|
||||||
|
@ -1050,6 +1088,7 @@ PropertiesView.prototype = {
|
||||||
if (!element) {
|
if (!element) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
element._identifier = aName;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see DebuggerView.Properties._setGrip
|
* @see DebuggerView.Properties._setGrip
|
||||||
|
@ -1382,16 +1421,22 @@ PropertiesView.prototype = {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Expands the element, showing all the added details.
|
* Expands the element, showing all the added details.
|
||||||
|
*
|
||||||
|
* @param boolean aSkipAnimationFlag
|
||||||
|
* Pass true to not show an opening animation.
|
||||||
* @return object
|
* @return object
|
||||||
* The same element.
|
* The same element.
|
||||||
*/
|
*/
|
||||||
element.expand = function DVP_element_expand() {
|
element.expand = function DVP_element_expand(aSkipAnimationFlag) {
|
||||||
if (element._preventExpand) {
|
if (element._preventExpand) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
arrow.setAttribute("open", "");
|
arrow.setAttribute("open", "");
|
||||||
details.setAttribute("open", "");
|
details.setAttribute("open", "");
|
||||||
|
|
||||||
|
if (!aSkipAnimationFlag) {
|
||||||
|
details.setAttribute("animated", "");
|
||||||
|
}
|
||||||
if ("function" === typeof element.onexpand) {
|
if ("function" === typeof element.onexpand) {
|
||||||
element.onexpand(element);
|
element.onexpand(element);
|
||||||
}
|
}
|
||||||
|
@ -1409,6 +1454,7 @@ PropertiesView.prototype = {
|
||||||
}
|
}
|
||||||
arrow.removeAttribute("open");
|
arrow.removeAttribute("open");
|
||||||
details.removeAttribute("open");
|
details.removeAttribute("open");
|
||||||
|
details.removeAttribute("animated");
|
||||||
|
|
||||||
if ("function" === typeof element.oncollapse) {
|
if ("function" === typeof element.oncollapse) {
|
||||||
element.oncollapse(element);
|
element.oncollapse(element);
|
||||||
|
@ -1621,7 +1667,7 @@ PropertiesView.prototype = {
|
||||||
children: {}
|
children: {}
|
||||||
};
|
};
|
||||||
|
|
||||||
store[element.id] = relation;
|
store[element._identifier] = relation;
|
||||||
element._root = relation.root;
|
element._root = relation.root;
|
||||||
element._children = relation.children;
|
element._children = relation.children;
|
||||||
},
|
},
|
||||||
|
@ -1633,11 +1679,16 @@ PropertiesView.prototype = {
|
||||||
createHierarchyStore: function DVP_createHierarchyStore() {
|
createHierarchyStore: function DVP_createHierarchyStore() {
|
||||||
this._prevHierarchy = this._currHierarchy;
|
this._prevHierarchy = this._currHierarchy;
|
||||||
this._currHierarchy = {};
|
this._currHierarchy = {};
|
||||||
|
},
|
||||||
|
|
||||||
this._saveHierarchy({ element: this._globalScope, store: this._currHierarchy });
|
/**
|
||||||
this._saveHierarchy({ element: this._localScope, store: this._currHierarchy });
|
* Creates a hierarchy holder for a scope.
|
||||||
this._saveHierarchy({ element: this._withScope, store: this._currHierarchy });
|
*
|
||||||
this._saveHierarchy({ element: this._closureScope, store: this._currHierarchy });
|
* @param object aScope
|
||||||
|
* The designated scope to track.
|
||||||
|
*/
|
||||||
|
addScopeToHierarchy: function DVP_addScopeToHierarchy(aScope) {
|
||||||
|
this._saveHierarchy({ element: aScope, store: this._currHierarchy });
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1648,6 +1699,10 @@ PropertiesView.prototype = {
|
||||||
let currScope = this._currHierarchy[i];
|
let currScope = this._currHierarchy[i];
|
||||||
let prevScope = this._prevHierarchy[i];
|
let prevScope = this._prevHierarchy[i];
|
||||||
|
|
||||||
|
if (!prevScope) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
for (let v in currScope.children) {
|
for (let v in currScope.children) {
|
||||||
let currVar = currScope.children[v];
|
let currVar = currScope.children[v];
|
||||||
let prevVar = prevScope.children[v];
|
let prevVar = prevScope.children[v];
|
||||||
|
@ -1685,103 +1740,11 @@ PropertiesView.prototype = {
|
||||||
_currHierarchy: null,
|
_currHierarchy: null,
|
||||||
_prevHierarchy: null,
|
_prevHierarchy: null,
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the global scope container.
|
|
||||||
*/
|
|
||||||
get globalScope() {
|
|
||||||
return this._globalScope;
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the display mode for the global scope container.
|
|
||||||
*
|
|
||||||
* @param boolean aFlag
|
|
||||||
* False to hide the container, true to show.
|
|
||||||
*/
|
|
||||||
set globalScope(aFlag) {
|
|
||||||
if (aFlag) {
|
|
||||||
this._globalScope.show();
|
|
||||||
} else {
|
|
||||||
this._globalScope.hide();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the local scope container.
|
|
||||||
*/
|
|
||||||
get localScope() {
|
|
||||||
return this._localScope;
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the display mode for the local scope container.
|
|
||||||
*
|
|
||||||
* @param boolean aFlag
|
|
||||||
* False to hide the container, true to show.
|
|
||||||
*/
|
|
||||||
set localScope(aFlag) {
|
|
||||||
if (aFlag) {
|
|
||||||
this._localScope.show();
|
|
||||||
} else {
|
|
||||||
this._localScope.hide();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the with block scope container.
|
|
||||||
*/
|
|
||||||
get withScope() {
|
|
||||||
return this._withScope;
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the display mode for the with block scope container.
|
|
||||||
*
|
|
||||||
* @param boolean aFlag
|
|
||||||
* False to hide the container, true to show.
|
|
||||||
*/
|
|
||||||
set withScope(aFlag) {
|
|
||||||
if (aFlag) {
|
|
||||||
this._withScope.show();
|
|
||||||
} else {
|
|
||||||
this._withScope.hide();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the closure scope container.
|
|
||||||
*/
|
|
||||||
get closureScope() {
|
|
||||||
return this._closureScope;
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the display mode for the with block scope container.
|
|
||||||
*
|
|
||||||
* @param boolean aFlag
|
|
||||||
* False to hide the container, true to show.
|
|
||||||
*/
|
|
||||||
set closureScope(aFlag) {
|
|
||||||
if (aFlag) {
|
|
||||||
this._closureScope.show();
|
|
||||||
} else {
|
|
||||||
this._closureScope.hide();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The cached variable properties container.
|
* The cached variable properties container.
|
||||||
*/
|
*/
|
||||||
_vars: null,
|
_vars: null,
|
||||||
|
|
||||||
/**
|
|
||||||
* Auto-created global, local, with block and closure scopes containing vars.
|
|
||||||
*/
|
|
||||||
_globalScope: null,
|
|
||||||
_localScope: null,
|
|
||||||
_withScope: null,
|
|
||||||
_closureScope: null,
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialization function, called when the debugger is initialized.
|
* Initialization function, called when the debugger is initialized.
|
||||||
*/
|
*/
|
||||||
|
@ -1789,10 +1752,6 @@ PropertiesView.prototype = {
|
||||||
this.createHierarchyStore();
|
this.createHierarchyStore();
|
||||||
|
|
||||||
this._vars = document.getElementById("variables");
|
this._vars = document.getElementById("variables");
|
||||||
this._localScope = this._addScope(L10N.getStr("localScope")).expand();
|
|
||||||
this._withScope = this._addScope(L10N.getStr("withScope")).hide();
|
|
||||||
this._closureScope = this._addScope(L10N.getStr("closureScope")).hide();
|
|
||||||
this._globalScope = this._addScope(L10N.getStr("globalScope"));
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1802,10 +1761,6 @@ PropertiesView.prototype = {
|
||||||
this._currHierarchy = null;
|
this._currHierarchy = null;
|
||||||
this._prevHierarchy = null;
|
this._prevHierarchy = null;
|
||||||
this._vars = null;
|
this._vars = null;
|
||||||
this._globalScope = null;
|
|
||||||
this._localScope = null;
|
|
||||||
this._withScope = null;
|
|
||||||
this._closureScope = null;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -30,6 +30,8 @@ _BROWSER_TEST_FILES = \
|
||||||
browser_dbg_propertyview-06.js \
|
browser_dbg_propertyview-06.js \
|
||||||
browser_dbg_propertyview-07.js \
|
browser_dbg_propertyview-07.js \
|
||||||
browser_dbg_propertyview-08.js \
|
browser_dbg_propertyview-08.js \
|
||||||
|
browser_dbg_propertyview-09.js \
|
||||||
|
browser_dbg_propertyview-10.js \
|
||||||
browser_dbg_propertyview-edit.js \
|
browser_dbg_propertyview-edit.js \
|
||||||
browser_dbg_panesize.js \
|
browser_dbg_panesize.js \
|
||||||
browser_dbg_stack-01.js \
|
browser_dbg_stack-01.js \
|
||||||
|
@ -66,6 +68,7 @@ _BROWSER_TEST_PAGES = \
|
||||||
test-editor-mode \
|
test-editor-mode \
|
||||||
browser_dbg_displayName.html \
|
browser_dbg_displayName.html \
|
||||||
browser_dbg_iframes.html \
|
browser_dbg_iframes.html \
|
||||||
|
browser_dbg_with-frame.html \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
libs:: $(_BROWSER_TEST_FILES)
|
libs:: $(_BROWSER_TEST_FILES)
|
||||||
|
|
|
@ -23,65 +23,14 @@ function testSimpleCall() {
|
||||||
gDebugger.DebuggerController.activeThread.addOneTimeListener("framesadded", function() {
|
gDebugger.DebuggerController.activeThread.addOneTimeListener("framesadded", function() {
|
||||||
Services.tm.currentThread.dispatch({ run: function() {
|
Services.tm.currentThread.dispatch({ run: function() {
|
||||||
|
|
||||||
let globalScope = gDebugger.DebuggerView.Properties._globalScope;
|
testScriptLabelShortening();
|
||||||
let localScope = gDebugger.DebuggerView.Properties._localScope;
|
|
||||||
let withScope = gDebugger.DebuggerView.Properties._withScope;
|
|
||||||
let closureScope = gDebugger.DebuggerView.Properties._closureScope;
|
|
||||||
|
|
||||||
ok(globalScope,
|
|
||||||
"Should have a globalScope container for the variables property view.");
|
|
||||||
|
|
||||||
ok(localScope,
|
|
||||||
"Should have a localScope container for the variables property view.");
|
|
||||||
|
|
||||||
ok(withScope,
|
|
||||||
"Should have a withScope container for the variables property view.");
|
|
||||||
|
|
||||||
ok(closureScope,
|
|
||||||
"Should have a closureScope container for the variables property view.");
|
|
||||||
|
|
||||||
is(globalScope, gDebugger.DebuggerView.Properties.globalScope,
|
|
||||||
"The globalScope object should be equal to the corresponding getter.");
|
|
||||||
|
|
||||||
is(localScope, gDebugger.DebuggerView.Properties.localScope,
|
|
||||||
"The localScope object should be equal to the corresponding getter.");
|
|
||||||
|
|
||||||
is(withScope, gDebugger.DebuggerView.Properties.withScope,
|
|
||||||
"The withScope object should be equal to the corresponding getter.");
|
|
||||||
|
|
||||||
is(closureScope, gDebugger.DebuggerView.Properties.closureScope,
|
|
||||||
"The closureScope object should be equal to the corresponding getter.");
|
|
||||||
|
|
||||||
|
|
||||||
ok(!globalScope.expanded,
|
|
||||||
"The globalScope should be initially collapsed.");
|
|
||||||
|
|
||||||
ok(localScope.expanded,
|
|
||||||
"The localScope should be initially expanded.");
|
|
||||||
|
|
||||||
ok(!withScope.expanded,
|
|
||||||
"The withScope should be initially collapsed.");
|
|
||||||
|
|
||||||
ok(!withScope.visible,
|
|
||||||
"The withScope should be initially hidden.");
|
|
||||||
|
|
||||||
ok(!closureScope.expanded,
|
|
||||||
"The closureScope should be initially collapsed.");
|
|
||||||
|
|
||||||
ok(!closureScope.visible,
|
|
||||||
"The closureScope should be initially hidden.");
|
|
||||||
|
|
||||||
is(gDebugger.DebuggerView.Properties._vars.childNodes.length, 4,
|
|
||||||
"Should have only 4 scopes created: global, local, with and scope.");
|
|
||||||
|
|
||||||
resumeAndFinish();
|
|
||||||
}}, 0);
|
}}, 0);
|
||||||
});
|
});
|
||||||
|
|
||||||
gDebuggee.simpleCall();
|
gDebuggee.simpleCall();
|
||||||
}
|
}
|
||||||
|
|
||||||
function resumeAndFinish() {
|
function testScriptLabelShortening() {
|
||||||
gDebugger.DebuggerController.activeThread.resume(function() {
|
gDebugger.DebuggerController.activeThread.resume(function() {
|
||||||
let vs = gDebugger.DebuggerView.Scripts;
|
let vs = gDebugger.DebuggerView.Scripts;
|
||||||
let ss = gDebugger.DebuggerController.SourceScripts;
|
let ss = gDebugger.DebuggerController.SourceScripts;
|
||||||
|
|
|
@ -28,7 +28,7 @@ function testSimpleCall() {
|
||||||
ok(testScope,
|
ok(testScope,
|
||||||
"Should have created a scope.");
|
"Should have created a scope.");
|
||||||
|
|
||||||
is(testScope.id, "test-scope",
|
is(testScope.id.substring(0, 4), "test",
|
||||||
"The newly created scope should have the default id set.");
|
"The newly created scope should have the default id set.");
|
||||||
|
|
||||||
is(testScope.querySelector(".name").getAttribute("value"), "test",
|
is(testScope.querySelector(".name").getAttribute("value"), "test",
|
||||||
|
@ -37,8 +37,8 @@ function testSimpleCall() {
|
||||||
is(testScope.querySelector(".details").childNodes.length, 0,
|
is(testScope.querySelector(".details").childNodes.length, 0,
|
||||||
"Any new scope should have a container with no child nodes.");
|
"Any new scope should have a container with no child nodes.");
|
||||||
|
|
||||||
is(gDebugger.DebuggerView.Properties._vars.childNodes.length, 5,
|
is(gDebugger.DebuggerView.Properties._vars.childNodes.length, 3,
|
||||||
"Should have 5 scopes created: global, local, with, closure and test.");
|
"Should have 3 scopes created.");
|
||||||
|
|
||||||
|
|
||||||
ok(!testScope.expanded,
|
ok(!testScope.expanded,
|
||||||
|
|
|
@ -23,7 +23,7 @@ function testSimpleCall() {
|
||||||
gDebugger.DebuggerController.activeThread.addOneTimeListener("framesadded", function() {
|
gDebugger.DebuggerController.activeThread.addOneTimeListener("framesadded", function() {
|
||||||
Services.tm.currentThread.dispatch({ run: function() {
|
Services.tm.currentThread.dispatch({ run: function() {
|
||||||
|
|
||||||
let testScope = gDebugger.DebuggerView.Properties._addScope("test");
|
let testScope = gDebugger.DebuggerView.Properties._addScope("test-scope");
|
||||||
let testVar = testScope.addVar("something");
|
let testVar = testScope.addVar("something");
|
||||||
let duplVar = testScope.addVar("something");
|
let duplVar = testScope.addVar("something");
|
||||||
|
|
||||||
|
@ -33,9 +33,6 @@ function testSimpleCall() {
|
||||||
is(duplVar, null,
|
is(duplVar, null,
|
||||||
"Shouldn't be able to duplicate variables in the same scope.");
|
"Shouldn't be able to duplicate variables in the same scope.");
|
||||||
|
|
||||||
is(testVar.id, "test-scope->something-variable",
|
|
||||||
"The newly created scope should have the default id set.");
|
|
||||||
|
|
||||||
is(testVar.querySelector(".name").getAttribute("value"), "something",
|
is(testVar.querySelector(".name").getAttribute("value"), "something",
|
||||||
"Any new variable should have the designated title.");
|
"Any new variable should have the designated title.");
|
||||||
|
|
||||||
|
@ -188,7 +185,7 @@ function testSimpleCall() {
|
||||||
is(removeCallbackSender, testScope,
|
is(removeCallbackSender, testScope,
|
||||||
"The removeCallback wasn't called as it should.");
|
"The removeCallback wasn't called as it should.");
|
||||||
|
|
||||||
is(gDebugger.DebuggerView.Properties._vars.childNodes.length, 4,
|
is(gDebugger.DebuggerView.Properties._vars.childNodes.length, 2,
|
||||||
"The scope should have been removed from the parent container tree.");
|
"The scope should have been removed from the parent container tree.");
|
||||||
|
|
||||||
gDebugger.DebuggerController.activeThread.resume(function() {
|
gDebugger.DebuggerController.activeThread.resume(function() {
|
||||||
|
|
|
@ -23,8 +23,8 @@ function testSimpleCall() {
|
||||||
gDebugger.DebuggerController.activeThread.addOneTimeListener("framesadded", function() {
|
gDebugger.DebuggerController.activeThread.addOneTimeListener("framesadded", function() {
|
||||||
Services.tm.currentThread.dispatch({ run: function() {
|
Services.tm.currentThread.dispatch({ run: function() {
|
||||||
|
|
||||||
let globalScope = gDebugger.DebuggerView.Properties.globalScope;
|
let globalScope = gDebugger.DebuggerView.Properties.addScope("Global");
|
||||||
let localScope = gDebugger.DebuggerView.Properties.localScope;
|
let localScope = gDebugger.DebuggerView.Properties.addScope("Local");
|
||||||
globalScope.empty();
|
globalScope.empty();
|
||||||
localScope.empty();
|
localScope.empty();
|
||||||
|
|
||||||
|
|
|
@ -37,7 +37,7 @@ function testFrameParameters()
|
||||||
|
|
||||||
var frames = gDebugger.DebuggerView.StackFrames._frames,
|
var frames = gDebugger.DebuggerView.StackFrames._frames,
|
||||||
childNodes = frames.childNodes,
|
childNodes = frames.childNodes,
|
||||||
localScope = gDebugger.DebuggerView.Properties.localScope,
|
localScope = gDebugger.DebuggerView.Properties._vars.firstChild,
|
||||||
localNodes = localScope.querySelector(".details").childNodes;
|
localNodes = localScope.querySelector(".details").childNodes;
|
||||||
|
|
||||||
dump("Got our variables:\n");
|
dump("Got our variables:\n");
|
||||||
|
@ -79,14 +79,14 @@ function testFrameParameters()
|
||||||
is(localNodes[7].querySelector(".value").getAttribute("value"), "1",
|
is(localNodes[7].querySelector(".value").getAttribute("value"), "1",
|
||||||
"Should have the right property value for 'a'.");
|
"Should have the right property value for 'a'.");
|
||||||
|
|
||||||
is(localNodes[8].querySelector(".value").getAttribute("value"), "[object Object]",
|
is(localNodes[8].querySelector(".value").getAttribute("value"), "[object Arguments]",
|
||||||
"Should have the right property value for 'b'.");
|
"Should have the right property value for 'arguments'.");
|
||||||
|
|
||||||
is(localNodes[9].querySelector(".value").getAttribute("value"), "[object Object]",
|
is(localNodes[9].querySelector(".value").getAttribute("value"), "[object Object]",
|
||||||
"Should have the right property value for 'c'.");
|
"Should have the right property value for 'b'.");
|
||||||
|
|
||||||
is(localNodes[10].querySelector(".value").getAttribute("value"), "[object Arguments]",
|
is(localNodes[10].querySelector(".value").getAttribute("value"), "[object Object]",
|
||||||
"Should have the right property value for 'arguments'.");
|
"Should have the right property value for 'c'.");
|
||||||
|
|
||||||
resumeAndFinish();
|
resumeAndFinish();
|
||||||
}}, 0);
|
}}, 0);
|
||||||
|
|
|
@ -36,7 +36,7 @@ function testFrameParameters()
|
||||||
dump("After currentThread.dispatch!\n");
|
dump("After currentThread.dispatch!\n");
|
||||||
|
|
||||||
var frames = gDebugger.DebuggerView.StackFrames._frames,
|
var frames = gDebugger.DebuggerView.StackFrames._frames,
|
||||||
localScope = gDebugger.DebuggerView.Properties.localScope,
|
localScope = gDebugger.DebuggerView.Properties._vars.firstChild,
|
||||||
localNodes = localScope.querySelector(".details").childNodes;
|
localNodes = localScope.querySelector(".details").childNodes;
|
||||||
|
|
||||||
dump("Got our variables:\n");
|
dump("Got our variables:\n");
|
||||||
|
@ -59,7 +59,7 @@ function testFrameParameters()
|
||||||
// Expand the 'this', 'arguments' and 'c' tree nodes. This causes
|
// Expand the 'this', 'arguments' and 'c' tree nodes. This causes
|
||||||
// their properties to be retrieved and displayed.
|
// their properties to be retrieved and displayed.
|
||||||
localNodes[0].expand();
|
localNodes[0].expand();
|
||||||
localNodes[9].expand();
|
localNodes[8].expand();
|
||||||
localNodes[10].expand();
|
localNodes[10].expand();
|
||||||
|
|
||||||
// Poll every few milliseconds until the properties are retrieved.
|
// Poll every few milliseconds until the properties are retrieved.
|
||||||
|
@ -73,7 +73,7 @@ function testFrameParameters()
|
||||||
resumeAndFinish();
|
resumeAndFinish();
|
||||||
}
|
}
|
||||||
if (!localNodes[0].fetched ||
|
if (!localNodes[0].fetched ||
|
||||||
!localNodes[9].fetched ||
|
!localNodes[8].fetched ||
|
||||||
!localNodes[10].fetched) {
|
!localNodes[10].fetched) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -86,29 +86,29 @@ function testFrameParameters()
|
||||||
.getAttribute("value").search(/object/) != -1,
|
.getAttribute("value").search(/object/) != -1,
|
||||||
"__proto__ should be an object.");
|
"__proto__ should be an object.");
|
||||||
|
|
||||||
is(localNodes[9].querySelector(".value").getAttribute("value"), "[object Object]",
|
is(localNodes[8].querySelector(".value").getAttribute("value"),
|
||||||
"Should have the right property value for 'c'.");
|
|
||||||
|
|
||||||
is(localNodes[9].querySelectorAll(".property > .title > .key")[1]
|
|
||||||
.getAttribute("value"), "a",
|
|
||||||
"Should have the right property name for 'a'.");
|
|
||||||
|
|
||||||
is(localNodes[9].querySelectorAll(".property > .title > .value")[1]
|
|
||||||
.getAttribute("value"), 1,
|
|
||||||
"Should have the right value for 'c.a'.");
|
|
||||||
|
|
||||||
is(localNodes[10].querySelector(".value").getAttribute("value"),
|
|
||||||
"[object Arguments]",
|
"[object Arguments]",
|
||||||
"Should have the right property value for 'arguments'.");
|
"Should have the right property value for 'arguments'.");
|
||||||
|
|
||||||
is(localNodes[10].querySelectorAll(".property > .title > .key")[7]
|
is(localNodes[8].querySelectorAll(".property > .title > .key")[7]
|
||||||
.getAttribute("value"), "length",
|
.getAttribute("value"), "length",
|
||||||
"Should have the right property name for 'length'.");
|
"Should have the right property name for 'length'.");
|
||||||
|
|
||||||
is(localNodes[10].querySelectorAll(".property > .title > .value")[7]
|
is(localNodes[8].querySelectorAll(".property > .title > .value")[7]
|
||||||
.getAttribute("value"), 5,
|
.getAttribute("value"), 5,
|
||||||
"Should have the right argument length.");
|
"Should have the right argument length.");
|
||||||
|
|
||||||
|
is(localNodes[10].querySelector(".value").getAttribute("value"), "[object Object]",
|
||||||
|
"Should have the right property value for 'c'.");
|
||||||
|
|
||||||
|
is(localNodes[10].querySelectorAll(".property > .title > .key")[1]
|
||||||
|
.getAttribute("value"), "a",
|
||||||
|
"Should have the right property name for 'a'.");
|
||||||
|
|
||||||
|
is(localNodes[10].querySelectorAll(".property > .title > .value")[1]
|
||||||
|
.getAttribute("value"), 1,
|
||||||
|
"Should have the right value for 'c.a'.");
|
||||||
|
|
||||||
resumeAndFinish();
|
resumeAndFinish();
|
||||||
}, 100);
|
}, 100);
|
||||||
}}, 0);
|
}}, 0);
|
||||||
|
|
|
@ -0,0 +1,94 @@
|
||||||
|
/* vim:set ts=2 sw=2 sts=2 et: */
|
||||||
|
/* Any copyright is dedicated to the Public Domain.
|
||||||
|
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Make sure that the property view populates the global scope pane.
|
||||||
|
*/
|
||||||
|
|
||||||
|
const TAB_URL = EXAMPLE_URL + "browser_dbg_frame-parameters.html";
|
||||||
|
|
||||||
|
var gPane = null;
|
||||||
|
var gTab = null;
|
||||||
|
var gDebugger = null;
|
||||||
|
|
||||||
|
function test()
|
||||||
|
{
|
||||||
|
debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) {
|
||||||
|
gTab = aTab;
|
||||||
|
gPane = aPane;
|
||||||
|
gDebugger = gPane.contentWindow;
|
||||||
|
|
||||||
|
testFrameParameters();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function testFrameParameters()
|
||||||
|
{
|
||||||
|
let count = 0;
|
||||||
|
gDebugger.addEventListener("Debugger:FetchedVariables", function test() {
|
||||||
|
// We expect 2 Debugger:FetchedVariables events, one from the global object
|
||||||
|
// scope and the regular one.
|
||||||
|
if (++count <2) {
|
||||||
|
info("Number of received Debugger:FetchedVariables events: " + count);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
gDebugger.removeEventListener("Debugger:FetchedVariables", test, false);
|
||||||
|
Services.tm.currentThread.dispatch({ run: function() {
|
||||||
|
|
||||||
|
var frames = gDebugger.DebuggerView.StackFrames._frames,
|
||||||
|
globalScope = gDebugger.DebuggerView.Properties._vars.lastChild,
|
||||||
|
globalNodes = globalScope.querySelector(".details").childNodes;
|
||||||
|
|
||||||
|
globalScope.expand();
|
||||||
|
|
||||||
|
is(gDebugger.DebuggerController.activeThread.state, "paused",
|
||||||
|
"Should only be getting stack frames while paused.");
|
||||||
|
|
||||||
|
is(frames.querySelectorAll(".dbg-stackframe").length, 3,
|
||||||
|
"Should have three frames.");
|
||||||
|
|
||||||
|
is(globalNodes[0].querySelector(".name").getAttribute("value"), "Array",
|
||||||
|
"Should have the right property name for |Array|.");
|
||||||
|
|
||||||
|
is(globalNodes[0].querySelector(".value").getAttribute("value"), "[object Function]",
|
||||||
|
"Should have the right property value for |Array|.");
|
||||||
|
|
||||||
|
let len = globalNodes.length - 1;
|
||||||
|
is(globalNodes[len].querySelector(".name").getAttribute("value"), "window",
|
||||||
|
"Should have the right property name for |window|.");
|
||||||
|
|
||||||
|
is(globalNodes[len].querySelector(".value").getAttribute("value"), "[object Proxy]",
|
||||||
|
"Should have the right property value for |window|.");
|
||||||
|
|
||||||
|
resumeAndFinish();
|
||||||
|
}}, 0);
|
||||||
|
}, false);
|
||||||
|
|
||||||
|
EventUtils.sendMouseEvent({ type: "click" },
|
||||||
|
content.document.querySelector("button"),
|
||||||
|
content.window);
|
||||||
|
}
|
||||||
|
|
||||||
|
function resumeAndFinish() {
|
||||||
|
gDebugger.addEventListener("Debugger:AfterFramesCleared", function listener() {
|
||||||
|
gDebugger.removeEventListener("Debugger:AfterFramesCleared", listener, true);
|
||||||
|
Services.tm.currentThread.dispatch({ run: function() {
|
||||||
|
var frames = gDebugger.DebuggerView.StackFrames._frames;
|
||||||
|
|
||||||
|
is(frames.querySelectorAll(".dbg-stackframe").length, 0,
|
||||||
|
"Should have no frames.");
|
||||||
|
|
||||||
|
closeDebuggerAndFinish(gTab);
|
||||||
|
}}, 0);
|
||||||
|
}, true);
|
||||||
|
|
||||||
|
gDebugger.DebuggerController.activeThread.resume();
|
||||||
|
}
|
||||||
|
|
||||||
|
registerCleanupFunction(function() {
|
||||||
|
removeTab(gTab);
|
||||||
|
gPane = null;
|
||||||
|
gTab = null;
|
||||||
|
gDebugger = null;
|
||||||
|
});
|
|
@ -0,0 +1,105 @@
|
||||||
|
/* vim:set ts=2 sw=2 sts=2 et: */
|
||||||
|
/* Any copyright is dedicated to the Public Domain.
|
||||||
|
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Make sure that the property view is correctly populated in |with| frames.
|
||||||
|
*/
|
||||||
|
|
||||||
|
const TAB_URL = EXAMPLE_URL + "browser_dbg_with-frame.html";
|
||||||
|
|
||||||
|
var gPane = null;
|
||||||
|
var gTab = null;
|
||||||
|
var gDebugger = null;
|
||||||
|
|
||||||
|
function test()
|
||||||
|
{
|
||||||
|
debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) {
|
||||||
|
gTab = aTab;
|
||||||
|
gPane = aPane;
|
||||||
|
gDebugger = gPane.contentWindow;
|
||||||
|
|
||||||
|
testWithFrame();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function testWithFrame()
|
||||||
|
{
|
||||||
|
let count = 0;
|
||||||
|
gDebugger.addEventListener("Debugger:FetchedVariables", function test() {
|
||||||
|
// We expect 4 Debugger:FetchedVariables events, one from the global object
|
||||||
|
// scope, two from the |with| scopes and the regular one.
|
||||||
|
if (++count <3) {
|
||||||
|
info("Number of received Debugger:FetchedVariables events: " + count);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
gDebugger.removeEventListener("Debugger:FetchedVariables", test, false);
|
||||||
|
Services.tm.currentThread.dispatch({ run: function() {
|
||||||
|
|
||||||
|
var frames = gDebugger.DebuggerView.StackFrames._frames,
|
||||||
|
scopes = gDebugger.DebuggerView.Properties._vars,
|
||||||
|
globalScope = scopes.lastChild,
|
||||||
|
innerScope = scopes.firstChild,
|
||||||
|
globalNodes = globalScope.querySelector(".details").childNodes,
|
||||||
|
innerNodes = innerScope.querySelector(".details").childNodes;
|
||||||
|
|
||||||
|
globalScope.expand();
|
||||||
|
|
||||||
|
is(gDebugger.DebuggerController.activeThread.state, "paused",
|
||||||
|
"Should only be getting stack frames while paused.");
|
||||||
|
|
||||||
|
is(frames.querySelectorAll(".dbg-stackframe").length, 2,
|
||||||
|
"Should have three frames.");
|
||||||
|
|
||||||
|
is(scopes.children.length, 5, "Should have 5 variable scopes.");
|
||||||
|
|
||||||
|
is(innerNodes[1].querySelector(".name").getAttribute("value"), "one",
|
||||||
|
"Should have the right property name for |one|.");
|
||||||
|
|
||||||
|
is(innerNodes[1].querySelector(".value").getAttribute("value"), "1",
|
||||||
|
"Should have the right property value for |one|.");
|
||||||
|
|
||||||
|
is(globalNodes[0].querySelector(".name").getAttribute("value"), "Array",
|
||||||
|
"Should have the right property name for |Array|.");
|
||||||
|
|
||||||
|
is(globalNodes[0].querySelector(".value").getAttribute("value"), "[object Function]",
|
||||||
|
"Should have the right property value for |Array|.");
|
||||||
|
|
||||||
|
let len = globalNodes.length - 1;
|
||||||
|
is(globalNodes[len].querySelector(".name").getAttribute("value"), "window",
|
||||||
|
"Should have the right property name for |window|.");
|
||||||
|
|
||||||
|
is(globalNodes[len].querySelector(".value").getAttribute("value"), "[object Proxy]",
|
||||||
|
"Should have the right property value for |window|.");
|
||||||
|
|
||||||
|
resumeAndFinish();
|
||||||
|
}}, 0);
|
||||||
|
}, false);
|
||||||
|
|
||||||
|
EventUtils.sendMouseEvent({ type: "click" },
|
||||||
|
content.document.querySelector("button"),
|
||||||
|
content.window);
|
||||||
|
}
|
||||||
|
|
||||||
|
function resumeAndFinish() {
|
||||||
|
gDebugger.addEventListener("Debugger:AfterFramesCleared", function listener() {
|
||||||
|
gDebugger.removeEventListener("Debugger:AfterFramesCleared", listener, true);
|
||||||
|
Services.tm.currentThread.dispatch({ run: function() {
|
||||||
|
var frames = gDebugger.DebuggerView.StackFrames._frames;
|
||||||
|
|
||||||
|
is(frames.querySelectorAll(".dbg-stackframe").length, 0,
|
||||||
|
"Should have no frames.");
|
||||||
|
|
||||||
|
closeDebuggerAndFinish(gTab);
|
||||||
|
}}, 0);
|
||||||
|
}, true);
|
||||||
|
|
||||||
|
gDebugger.DebuggerController.activeThread.resume();
|
||||||
|
}
|
||||||
|
|
||||||
|
registerCleanupFunction(function() {
|
||||||
|
removeTab(gTab);
|
||||||
|
gPane = null;
|
||||||
|
gTab = null;
|
||||||
|
gDebugger = null;
|
||||||
|
});
|
|
@ -29,7 +29,7 @@ function testFrameEval() {
|
||||||
is(gDebugger.DebuggerController.activeThread.state, "paused",
|
is(gDebugger.DebuggerController.activeThread.state, "paused",
|
||||||
"Should only be getting stack frames while paused.");
|
"Should only be getting stack frames while paused.");
|
||||||
|
|
||||||
var localScope = gDebugger.DebuggerView.Properties.localScope,
|
var localScope = gDebugger.DebuggerView.Properties._vars.firstChild,
|
||||||
localNodes = localScope.querySelector(".details").childNodes,
|
localNodes = localScope.querySelector(".details").childNodes,
|
||||||
varA = localNodes[7];
|
varA = localNodes[7];
|
||||||
|
|
||||||
|
@ -68,11 +68,18 @@ function testModification(aVar, aCallback, aNewValue, aNewResult) {
|
||||||
ok(aVar.querySelector(".element-input"),
|
ok(aVar.querySelector(".element-input"),
|
||||||
"There should be an input element created.");
|
"There should be an input element created.");
|
||||||
|
|
||||||
|
let count = 0;
|
||||||
gDebugger.addEventListener("Debugger:FetchedVariables", function test() {
|
gDebugger.addEventListener("Debugger:FetchedVariables", function test() {
|
||||||
|
// We expect 2 Debugger:FetchedVariables events, one from the global
|
||||||
|
// object scope and the regular one.
|
||||||
|
if (++count <2) {
|
||||||
|
info("Number of received Debugger:FetchedVariables events: " + count);
|
||||||
|
return;
|
||||||
|
}
|
||||||
gDebugger.removeEventListener("Debugger:FetchedVariables", test, false);
|
gDebugger.removeEventListener("Debugger:FetchedVariables", test, false);
|
||||||
// Get the variable reference anew, since the old ones were discarded when
|
// Get the variable reference anew, since the old ones were discarded when
|
||||||
// we resumed.
|
// we resumed.
|
||||||
var localScope = gDebugger.DebuggerView.Properties.localScope,
|
var localScope = gDebugger.DebuggerView.Properties._vars.firstChild,
|
||||||
localNodes = localScope.querySelector(".details").childNodes,
|
localNodes = localScope.querySelector(".details").childNodes,
|
||||||
varA = localNodes[7];
|
varA = localNodes[7];
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
<!DOCTYPE HTML>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset='utf-8'/>
|
||||||
|
<title>Debugger Function Call Parameter Test</title>
|
||||||
|
<!-- Any copyright is dedicated to the Public Domain.
|
||||||
|
http://creativecommons.org/publicdomain/zero/1.0/ -->
|
||||||
|
<script type="text/javascript">
|
||||||
|
window.addEventListener("load", function() {
|
||||||
|
function test(aNumber) {
|
||||||
|
var a, obj = { one: 1, two: 2 };
|
||||||
|
var r = aNumber;
|
||||||
|
with (Math) {
|
||||||
|
a = PI * r * r;
|
||||||
|
with (obj) {
|
||||||
|
var foo = two * PI;
|
||||||
|
debugger;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
function load() {
|
||||||
|
test(10);
|
||||||
|
}
|
||||||
|
var button = document.querySelector("button");
|
||||||
|
button.addEventListener("click", load, false);
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<button>Click me!</button>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -31,9 +31,7 @@ const console = (function() {
|
||||||
*/
|
*/
|
||||||
function define(moduleName, deps, payload) {
|
function define(moduleName, deps, payload) {
|
||||||
if (typeof moduleName != "string") {
|
if (typeof moduleName != "string") {
|
||||||
console.error(this.depth + " Error: Module name is not a string.");
|
throw new Error("Error: Module name is not a string");
|
||||||
console.trace();
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (arguments.length == 2) {
|
if (arguments.length == 2) {
|
||||||
|
@ -49,8 +47,11 @@ function define(moduleName, deps, payload) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (moduleName in define.modules) {
|
if (moduleName in define.modules) {
|
||||||
console.error(this.depth + " Error: Redefining module: " + moduleName);
|
throw new Error("Error: Redefining module: " + moduleName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Mark the payload so we know we need to call it to get the real module
|
||||||
|
payload.__uncompiled = true;
|
||||||
define.modules[moduleName] = payload;
|
define.modules[moduleName] = payload;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,14 +66,6 @@ define.modules = {};
|
||||||
define.debugDependencies = false;
|
define.debugDependencies = false;
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Self executing function in which Domain is defined, and attached to define
|
|
||||||
*/
|
|
||||||
var Syntax = {
|
|
||||||
COMMON_JS: 'commonjs',
|
|
||||||
AMD: 'amd'
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* We invoke require() in the context of a Domain so we can have multiple
|
* We invoke require() in the context of a Domain so we can have multiple
|
||||||
* sets of modules running separate from each other.
|
* sets of modules running separate from each other.
|
||||||
|
@ -83,7 +76,6 @@ var Syntax = {
|
||||||
*/
|
*/
|
||||||
function Domain() {
|
function Domain() {
|
||||||
this.modules = {};
|
this.modules = {};
|
||||||
this.syntax = Syntax.COMMON_JS;
|
|
||||||
|
|
||||||
if (define.debugDependencies) {
|
if (define.debugDependencies) {
|
||||||
this.depth = "";
|
this.depth = "";
|
||||||
|
@ -111,7 +103,6 @@ Domain.prototype.require = function(config, deps, callback) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Array.isArray(deps)) {
|
if (Array.isArray(deps)) {
|
||||||
this.syntax = Syntax.AMD;
|
|
||||||
var params = deps.map(function(dep) {
|
var params = deps.map(function(dep) {
|
||||||
return this.lookup(dep);
|
return this.lookup(dep);
|
||||||
}, this);
|
}, this);
|
||||||
|
@ -141,8 +132,7 @@ Domain.prototype.lookup = function(moduleName) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(moduleName in define.modules)) {
|
if (!(moduleName in define.modules)) {
|
||||||
console.error(this.depth + " Missing module: " + moduleName);
|
throw new Error("Missing module: " + moduleName);
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var module = define.modules[moduleName];
|
var module = define.modules[moduleName];
|
||||||
|
@ -151,29 +141,33 @@ Domain.prototype.lookup = function(moduleName) {
|
||||||
console.log(this.depth + " Compiling module: " + moduleName);
|
console.log(this.depth + " Compiling module: " + moduleName);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof module == "function") {
|
if (module.__uncompiled) {
|
||||||
if (define.debugDependencies) {
|
if (define.debugDependencies) {
|
||||||
this.depth += ".";
|
this.depth += ".";
|
||||||
}
|
}
|
||||||
|
|
||||||
var exports;
|
var exports = {};
|
||||||
try {
|
try {
|
||||||
if (this.syntax === Syntax.COMMON_JS) {
|
var params = module.deps.map(function(dep) {
|
||||||
exports = {};
|
if (dep === "require") {
|
||||||
module(this.require.bind(this), exports, { id: moduleName, uri: "" });
|
return this.require.bind(this);
|
||||||
|
}
|
||||||
|
if (dep === "exports") {
|
||||||
|
return exports;
|
||||||
|
}
|
||||||
|
if (dep === "module") {
|
||||||
|
return { id: moduleName, uri: "" };
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
var modules = module.deps.map(function(dep) {
|
|
||||||
return this.lookup(dep);
|
return this.lookup(dep);
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
exports = module.apply(null, modules);
|
|
||||||
}
|
var reply = module.apply(null, params);
|
||||||
|
module = (reply !== undefined) ? reply : exports;
|
||||||
}
|
}
|
||||||
catch (ex) {
|
catch (ex) {
|
||||||
console.error("Error using module: " + moduleName, ex);
|
dump("Error using module '" + moduleName + "' - " + ex + "\n");
|
||||||
throw ex;
|
throw ex;
|
||||||
}
|
}
|
||||||
module = exports;
|
|
||||||
|
|
||||||
if (define.debugDependencies) {
|
if (define.debugDependencies) {
|
||||||
this.depth = this.depth.slice(0, -1);
|
this.depth = this.depth.slice(0, -1);
|
||||||
|
|
|
@ -56,6 +56,7 @@ function Templater(options) {
|
||||||
else {
|
else {
|
||||||
this.stack = [];
|
this.stack = [];
|
||||||
}
|
}
|
||||||
|
this.nodes = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -93,6 +94,7 @@ Templater.prototype.processNode = function(node, data) {
|
||||||
data = {};
|
data = {};
|
||||||
}
|
}
|
||||||
this.stack.push(node.nodeName + (node.id ? '#' + node.id : ''));
|
this.stack.push(node.nodeName + (node.id ? '#' + node.id : ''));
|
||||||
|
var pushedNode = false;
|
||||||
try {
|
try {
|
||||||
// Process attributes
|
// Process attributes
|
||||||
if (node.attributes && node.attributes.length) {
|
if (node.attributes && node.attributes.length) {
|
||||||
|
@ -109,7 +111,9 @@ Templater.prototype.processNode = function(node, data) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Only make the node available once we know it's not going away
|
// Only make the node available once we know it's not going away
|
||||||
|
this.nodes.push(data.__element);
|
||||||
data.__element = node;
|
data.__element = node;
|
||||||
|
pushedNode = true;
|
||||||
// It's good to clean up the attributes when we've processed them,
|
// It's good to clean up the attributes when we've processed them,
|
||||||
// but if we do it straight away, we mess up the array index
|
// but if we do it straight away, we mess up the array index
|
||||||
var attrs = Array.prototype.slice.call(node.attributes);
|
var attrs = Array.prototype.slice.call(node.attributes);
|
||||||
|
@ -172,7 +176,9 @@ Templater.prototype.processNode = function(node, data) {
|
||||||
this._processTextNode(node, data);
|
this._processTextNode(node, data);
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
delete data.__element;
|
if (pushedNode) {
|
||||||
|
data.__element = this.nodes.pop();
|
||||||
|
}
|
||||||
this.stack.pop();
|
this.stack.pop();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -347,11 +353,14 @@ Templater.prototype._processTextNode = function(node, data) {
|
||||||
reply = this._maybeImportNode(reply, doc);
|
reply = this._maybeImportNode(reply, doc);
|
||||||
siblingNode.parentNode.insertBefore(reply, siblingNode);
|
siblingNode.parentNode.insertBefore(reply, siblingNode);
|
||||||
} else if (typeof reply.item === 'function' && reply.length) {
|
} else if (typeof reply.item === 'function' && reply.length) {
|
||||||
// if thing is a NodeList, then import the children
|
// NodeLists can be live, in which case _maybeImportNode can
|
||||||
for (var i = 0; i < reply.length; i++) {
|
// remove them from the document, and thus the NodeList, which in
|
||||||
var child = this._maybeImportNode(reply.item(i), doc);
|
// turn breaks iteration. So first we clone the list
|
||||||
siblingNode.parentNode.insertBefore(child, siblingNode);
|
var list = Array.prototype.slice.call(reply, 0);
|
||||||
}
|
list.forEach(function(child) {
|
||||||
|
var imported = this._maybeImportNode(child, doc);
|
||||||
|
siblingNode.parentNode.insertBefore(imported, siblingNode);
|
||||||
|
}.bind(this));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// if thing isn't a DOM element then wrap its string value in one
|
// if thing isn't a DOM element then wrap its string value in one
|
||||||
|
|
|
@ -21,13 +21,14 @@ function test() {
|
||||||
testMultiImport();
|
testMultiImport();
|
||||||
testRecursive();
|
testRecursive();
|
||||||
testUncompilable();
|
testUncompilable();
|
||||||
|
testFirebug();
|
||||||
|
|
||||||
shutdown();
|
shutdown();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function setup() {
|
function setup() {
|
||||||
define('gclitest/requirable', [], function(require, exports, module) {
|
define('gclitest/requirable', [ 'require', 'exports', 'module' ], function(require, exports, module) {
|
||||||
exports.thing1 = 'thing1';
|
exports.thing1 = 'thing1';
|
||||||
exports.thing2 = 2;
|
exports.thing2 = 2;
|
||||||
|
|
||||||
|
@ -36,13 +37,17 @@ function setup() {
|
||||||
exports.getStatus = function() { return status; };
|
exports.getStatus = function() { return status; };
|
||||||
});
|
});
|
||||||
|
|
||||||
define('gclitest/unrequirable', [], function(require, exports, module) {
|
define('gclitest/unrequirable', [ 'require', 'exports', 'module' ], function(require, exports, module) {
|
||||||
null.throwNPE();
|
null.throwNPE();
|
||||||
});
|
});
|
||||||
|
|
||||||
define('gclitest/recurse', [], function(require, exports, module) {
|
define('gclitest/recurse', [ 'require', 'exports', 'module', 'gclitest/recurse' ], function(require, exports, module) {
|
||||||
require('gclitest/recurse');
|
require('gclitest/recurse');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
define('gclitest/firebug', [ 'gclitest/requirable' ], function(requirable) {
|
||||||
|
return { requirable: requirable, fb: true };
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function shutdown() {
|
function shutdown() {
|
||||||
|
@ -52,6 +57,8 @@ function shutdown() {
|
||||||
delete define.globalDomain.modules['gclitest/unrequirable'];
|
delete define.globalDomain.modules['gclitest/unrequirable'];
|
||||||
delete define.modules['gclitest/recurse'];
|
delete define.modules['gclitest/recurse'];
|
||||||
delete define.globalDomain.modules['gclitest/recurse'];
|
delete define.globalDomain.modules['gclitest/recurse'];
|
||||||
|
delete define.modules['gclitest/firebug'];
|
||||||
|
delete define.globalDomain.modules['gclitest/firebug'];
|
||||||
|
|
||||||
define = undefined;
|
define = undefined;
|
||||||
require = undefined;
|
require = undefined;
|
||||||
|
@ -124,3 +131,10 @@ function testRecursive() {
|
||||||
// require('gclitest/recurse');
|
// require('gclitest/recurse');
|
||||||
// Also see the comments in the testRecursive() function
|
// Also see the comments in the testRecursive() function
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function testFirebug() {
|
||||||
|
let requirable = require('gclitest/requirable');
|
||||||
|
let firebug = require('gclitest/firebug');
|
||||||
|
ok(firebug.fb, 'firebug.fb is true');
|
||||||
|
is(requirable, firebug.requirable, 'requirable pass-through');
|
||||||
|
}
|
||||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -13,6 +13,7 @@ include $(DEPTH)/config/autoconf.mk
|
||||||
EXTRA_JS_MODULES = \
|
EXTRA_JS_MODULES = \
|
||||||
PropertyPanel.jsm \
|
PropertyPanel.jsm \
|
||||||
NetworkHelper.jsm \
|
NetworkHelper.jsm \
|
||||||
|
NetworkPanel.jsm \
|
||||||
AutocompletePopup.jsm \
|
AutocompletePopup.jsm \
|
||||||
WebConsoleUtils.jsm \
|
WebConsoleUtils.jsm \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
|
@ -49,6 +49,7 @@
|
||||||
* Austin Andrews
|
* Austin Andrews
|
||||||
* Christoph Dorn
|
* Christoph Dorn
|
||||||
* Steven Roussey (AppCenter Inc, Network54)
|
* Steven Roussey (AppCenter Inc, Network54)
|
||||||
|
* Mihai Sucan (Mozilla Corp.)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const Cc = Components.classes;
|
const Cc = Components.classes;
|
||||||
|
@ -68,7 +69,7 @@ var EXPORTED_SYMBOLS = ["NetworkHelper"];
|
||||||
/**
|
/**
|
||||||
* Helper object for networking stuff.
|
* Helper object for networking stuff.
|
||||||
*
|
*
|
||||||
* All of the following functions have been taken from the Firebug source. They
|
* Most of the following functions have been taken from the Firebug source. They
|
||||||
* have been modified to match the Firefox coding rules.
|
* have been modified to match the Firefox coding rules.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -128,12 +129,13 @@ var NetworkHelper =
|
||||||
* Reads the posted text from aRequest.
|
* Reads the posted text from aRequest.
|
||||||
*
|
*
|
||||||
* @param nsIHttpChannel aRequest
|
* @param nsIHttpChannel aRequest
|
||||||
* @param nsIDOMNode aBrowser
|
* @param string aCharset
|
||||||
|
* The content document charset, used when reading the POSTed data.
|
||||||
* @returns string or null
|
* @returns string or null
|
||||||
* Returns the posted string if it was possible to read from aRequest
|
* Returns the posted string if it was possible to read from aRequest
|
||||||
* otherwise null.
|
* otherwise null.
|
||||||
*/
|
*/
|
||||||
readPostTextFromRequest: function NH_readPostTextFromRequest(aRequest, aBrowser)
|
readPostTextFromRequest: function NH_readPostTextFromRequest(aRequest, aCharset)
|
||||||
{
|
{
|
||||||
if (aRequest instanceof Ci.nsIUploadChannel) {
|
if (aRequest instanceof Ci.nsIUploadChannel) {
|
||||||
let iStream = aRequest.uploadStream;
|
let iStream = aRequest.uploadStream;
|
||||||
|
@ -150,8 +152,7 @@ var NetworkHelper =
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read data from the stream.
|
// Read data from the stream.
|
||||||
let charset = aBrowser.contentWindow.document.characterSet;
|
let text = this.readAndConvertFromStream(iStream, aCharset);
|
||||||
let text = this.readAndConvertFromStream(iStream, charset);
|
|
||||||
|
|
||||||
// Seek locks the file, so seek to the beginning only if necko hasn't
|
// Seek locks the file, so seek to the beginning only if necko hasn't
|
||||||
// read it yet, since necko doesn't seek to 0 before reading (at lest
|
// read it yet, since necko doesn't seek to 0 before reading (at lest
|
||||||
|
@ -167,14 +168,15 @@ var NetworkHelper =
|
||||||
/**
|
/**
|
||||||
* Reads the posted text from the page's cache.
|
* Reads the posted text from the page's cache.
|
||||||
*
|
*
|
||||||
* @param nsIDOMNode aBrowser
|
* @param nsIDocShell aDocShell
|
||||||
|
* @param string aCharset
|
||||||
* @returns string or null
|
* @returns string or null
|
||||||
* Returns the posted string if it was possible to read from aBrowser
|
* Returns the posted string if it was possible to read from
|
||||||
* otherwise null.
|
* aDocShell otherwise null.
|
||||||
*/
|
*/
|
||||||
readPostTextFromPage: function NH_readPostTextFromPage(aBrowser)
|
readPostTextFromPage: function NH_readPostTextFromPage(aDocShell, aCharset)
|
||||||
{
|
{
|
||||||
let webNav = aBrowser.webNavigation;
|
let webNav = aDocShell.QueryInterface(Ci.nsIWebNavigation);
|
||||||
if (webNav instanceof Ci.nsIWebPageDescriptor) {
|
if (webNav instanceof Ci.nsIWebPageDescriptor) {
|
||||||
let descriptor = webNav.currentDescriptor;
|
let descriptor = webNav.currentDescriptor;
|
||||||
|
|
||||||
|
@ -182,8 +184,7 @@ var NetworkHelper =
|
||||||
descriptor instanceof Ci.nsISeekableStream) {
|
descriptor instanceof Ci.nsISeekableStream) {
|
||||||
descriptor.seek(NS_SEEK_SET, 0);
|
descriptor.seek(NS_SEEK_SET, 0);
|
||||||
|
|
||||||
let charset = browser.contentWindow.document.characterSet;
|
return this.readAndConvertFromStream(descriptor, aCharset);
|
||||||
return this.readAndConvertFromStream(descriptor, charset);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
@ -266,6 +267,81 @@ var NetworkHelper =
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse a raw Cookie header value.
|
||||||
|
*
|
||||||
|
* @param string aHeader
|
||||||
|
* The raw Cookie header value.
|
||||||
|
* @return array
|
||||||
|
* Array holding an object for each cookie. Each object holds the
|
||||||
|
* following properties: name and value.
|
||||||
|
*/
|
||||||
|
parseCookieHeader: function NH_parseCookieHeader(aHeader)
|
||||||
|
{
|
||||||
|
let cookies = aHeader.split(";");
|
||||||
|
let result = [];
|
||||||
|
|
||||||
|
cookies.forEach(function(aCookie) {
|
||||||
|
let [name, value] = aCookie.split("=");
|
||||||
|
result.push({name: unescape(name.trim()),
|
||||||
|
value: unescape(value.trim())});
|
||||||
|
});
|
||||||
|
|
||||||
|
return result;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse a raw Set-Cookie header value.
|
||||||
|
*
|
||||||
|
* @param string aHeader
|
||||||
|
* The raw Set-Cookie header value.
|
||||||
|
* @return array
|
||||||
|
* Array holding an object for each cookie. Each object holds the
|
||||||
|
* following properties: name, value, secure (boolean), httpOnly
|
||||||
|
* (boolean), path, domain and expires (ISO date string).
|
||||||
|
*/
|
||||||
|
parseSetCookieHeader: function NH_parseSetCookieHeader(aHeader)
|
||||||
|
{
|
||||||
|
let rawCookies = aHeader.split(/\r\n|\n|\r/);
|
||||||
|
let cookies = [];
|
||||||
|
|
||||||
|
rawCookies.forEach(function(aCookie) {
|
||||||
|
let name = unescape(aCookie.substr(0, aCookie.indexOf("=")).trim());
|
||||||
|
let parts = aCookie.substr(aCookie.indexOf("=") + 1).split(";");
|
||||||
|
let value = unescape(parts.shift().trim());
|
||||||
|
|
||||||
|
let cookie = {name: name, value: value};
|
||||||
|
|
||||||
|
parts.forEach(function(aPart) {
|
||||||
|
let part = aPart.trim();
|
||||||
|
if (part.toLowerCase() == "secure") {
|
||||||
|
cookie.secure = true;
|
||||||
|
}
|
||||||
|
else if (part.toLowerCase() == "httponly") {
|
||||||
|
cookie.httpOnly = true;
|
||||||
|
}
|
||||||
|
else if (part.indexOf("=") > -1) {
|
||||||
|
let pair = part.split("=");
|
||||||
|
pair[0] = pair[0].toLowerCase();
|
||||||
|
if (pair[0] == "path" || pair[0] == "domain") {
|
||||||
|
cookie[pair[0]] = pair[1];
|
||||||
|
}
|
||||||
|
else if (pair[0] == "expires") {
|
||||||
|
try {
|
||||||
|
pair[1] = pair[1].replace(/-/g, ' ');
|
||||||
|
cookie.expires = new Date(pair[1]).toISOString();
|
||||||
|
}
|
||||||
|
catch (ex) { }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
cookies.push(cookie);
|
||||||
|
});
|
||||||
|
|
||||||
|
return cookies;
|
||||||
|
},
|
||||||
|
|
||||||
// This is a list of all the mime category maps jviereck could find in the
|
// This is a list of all the mime category maps jviereck could find in the
|
||||||
// firebug code base.
|
// firebug code base.
|
||||||
mimeCategoryMap: {
|
mimeCategoryMap: {
|
||||||
|
@ -333,6 +409,7 @@ var NetworkHelper =
|
||||||
"audio/x-wav": "media",
|
"audio/x-wav": "media",
|
||||||
"text/json": "json",
|
"text/json": "json",
|
||||||
"application/x-json": "json",
|
"application/x-json": "json",
|
||||||
"application/json-rpc": "json"
|
"application/json-rpc": "json",
|
||||||
|
"application/x-web-app-manifest+json": "json",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,668 @@
|
||||||
|
/* -*- Mode: js2; js2-basic-offset: 2; indent-tabs-mode: nil; -*- */
|
||||||
|
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||||
|
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
const Cc = Components.classes;
|
||||||
|
const Ci = Components.interfaces;
|
||||||
|
const Cu = Components.utils;
|
||||||
|
|
||||||
|
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||||
|
|
||||||
|
XPCOMUtils.defineLazyServiceGetter(this, "mimeService", "@mozilla.org/mime;1",
|
||||||
|
"nsIMIMEService");
|
||||||
|
|
||||||
|
XPCOMUtils.defineLazyModuleGetter(this, "NetworkHelper",
|
||||||
|
"resource:///modules/NetworkHelper.jsm");
|
||||||
|
|
||||||
|
XPCOMUtils.defineLazyModuleGetter(this, "NetUtil",
|
||||||
|
"resource://gre/modules/NetUtil.jsm");
|
||||||
|
|
||||||
|
XPCOMUtils.defineLazyModuleGetter(this, "WebConsoleUtils",
|
||||||
|
"resource:///modules/WebConsoleUtils.jsm");
|
||||||
|
|
||||||
|
XPCOMUtils.defineLazyGetter(this, "l10n", function() {
|
||||||
|
return WebConsoleUtils.l10n;
|
||||||
|
});
|
||||||
|
|
||||||
|
var EXPORTED_SYMBOLS = ["NetworkPanel"];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new NetworkPanel.
|
||||||
|
*
|
||||||
|
* @param nsIDOMNode aParent
|
||||||
|
* Parent node to append the created panel to.
|
||||||
|
* @param object aHttpActivity
|
||||||
|
* HttpActivity to display in the panel.
|
||||||
|
*/
|
||||||
|
function NetworkPanel(aParent, aHttpActivity)
|
||||||
|
{
|
||||||
|
let doc = aParent.ownerDocument;
|
||||||
|
this.httpActivity = aHttpActivity;
|
||||||
|
|
||||||
|
// Create the underlaying panel
|
||||||
|
this.panel = createElement(doc, "panel", {
|
||||||
|
label: l10n.getStr("NetworkPanel.label"),
|
||||||
|
titlebar: "normal",
|
||||||
|
noautofocus: "true",
|
||||||
|
noautohide: "true",
|
||||||
|
close: "true"
|
||||||
|
});
|
||||||
|
|
||||||
|
// Create the iframe that displays the NetworkPanel XHTML.
|
||||||
|
this.iframe = createAndAppendElement(this.panel, "iframe", {
|
||||||
|
src: "chrome://browser/content/NetworkPanel.xhtml",
|
||||||
|
type: "content",
|
||||||
|
flex: "1"
|
||||||
|
});
|
||||||
|
|
||||||
|
let self = this;
|
||||||
|
|
||||||
|
// Destroy the panel when it's closed.
|
||||||
|
this.panel.addEventListener("popuphidden", function onPopupHide() {
|
||||||
|
self.panel.removeEventListener("popuphidden", onPopupHide, false);
|
||||||
|
self.panel.parentNode.removeChild(self.panel);
|
||||||
|
self.panel = null;
|
||||||
|
self.iframe = null;
|
||||||
|
self.document = null;
|
||||||
|
self.httpActivity = null;
|
||||||
|
|
||||||
|
if (self.linkNode) {
|
||||||
|
self.linkNode._panelOpen = false;
|
||||||
|
self.linkNode = null;
|
||||||
|
}
|
||||||
|
}, 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;
|
||||||
|
self.update();
|
||||||
|
}, true);
|
||||||
|
|
||||||
|
// Create the footer.
|
||||||
|
let footer = createElement(doc, "hbox", { align: "end" });
|
||||||
|
createAndAppendElement(footer, "spacer", { flex: 1 });
|
||||||
|
|
||||||
|
createAndAppendElement(footer, "resizer", { dir: "bottomend" });
|
||||||
|
this.panel.appendChild(footer);
|
||||||
|
|
||||||
|
aParent.appendChild(this.panel);
|
||||||
|
}
|
||||||
|
|
||||||
|
NetworkPanel.prototype =
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Callback is called once the NetworkPanel is processed completely. Used by
|
||||||
|
* unit tests.
|
||||||
|
*/
|
||||||
|
isDoneCallback: null,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The current state of the output.
|
||||||
|
*/
|
||||||
|
_state: 0,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* State variables.
|
||||||
|
*/
|
||||||
|
_INIT: 0,
|
||||||
|
_DISPLAYED_REQUEST_HEADER: 1,
|
||||||
|
_DISPLAYED_REQUEST_BODY: 2,
|
||||||
|
_DISPLAYED_RESPONSE_HEADER: 3,
|
||||||
|
_TRANSITION_CLOSED: 4,
|
||||||
|
|
||||||
|
_fromDataRegExp: /Content-Type\:\s*application\/x-www-form-urlencoded/,
|
||||||
|
|
||||||
|
_contentType: null,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Small helper function that is nearly equal to l10n.getFormatStr
|
||||||
|
* except that it prefixes aName with "NetworkPanel.".
|
||||||
|
*
|
||||||
|
* @param string aName
|
||||||
|
* The name of an i10n string to format. This string is prefixed with
|
||||||
|
* "NetworkPanel." before calling the HUDService.getFormatStr function.
|
||||||
|
* @param array aArray
|
||||||
|
* Values used as placeholder for the i10n string.
|
||||||
|
* @returns string
|
||||||
|
* The i10n formated string.
|
||||||
|
*/
|
||||||
|
_format: function NP_format(aName, aArray)
|
||||||
|
{
|
||||||
|
return l10n.getFormatStr("NetworkPanel." + aName, aArray);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the content type of the response body. This is based on the
|
||||||
|
* response.content.mimeType property. If this value is not available, then
|
||||||
|
* the content type is guessed by the file extension of the request URL.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
* Content type or empty string if no content type could be figured
|
||||||
|
* out.
|
||||||
|
*/
|
||||||
|
get contentType()
|
||||||
|
{
|
||||||
|
if (this._contentType) {
|
||||||
|
return this._contentType;
|
||||||
|
}
|
||||||
|
|
||||||
|
let entry = this.httpActivity.log.entries[0];
|
||||||
|
let request = entry.request;
|
||||||
|
let response = entry.response;
|
||||||
|
|
||||||
|
let contentType = "";
|
||||||
|
let types = response.content ?
|
||||||
|
(response.content.mimeType || "").split(/,|;/) : [];
|
||||||
|
for (let i = 0; i < types.length; i++) {
|
||||||
|
if (types[i] in NetworkHelper.mimeCategoryMap) {
|
||||||
|
contentType = types[i];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (contentType) {
|
||||||
|
this._contentType = contentType;
|
||||||
|
return contentType;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try to get the content type from the request file extension.
|
||||||
|
let uri = NetUtil.newURI(request.url);
|
||||||
|
if ((uri instanceof Ci.nsIURL) && uri.fileExtension) {
|
||||||
|
try {
|
||||||
|
contentType = mimeService.getTypeFromExtension(uri.fileExtension);
|
||||||
|
}
|
||||||
|
catch(ex) {
|
||||||
|
// Added to prevent failures on OS X 64. No Flash?
|
||||||
|
Cu.reportError(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this._contentType = contentType;
|
||||||
|
return contentType;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @returns boolean
|
||||||
|
* True if the response is an image, false otherwise.
|
||||||
|
*/
|
||||||
|
get _responseIsImage()
|
||||||
|
{
|
||||||
|
return this.contentType &&
|
||||||
|
NetworkHelper.mimeCategoryMap[this.contentType] == "image";
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @returns boolean
|
||||||
|
* True if the response body contains text, false otherwise.
|
||||||
|
*/
|
||||||
|
get _isResponseBodyTextData()
|
||||||
|
{
|
||||||
|
let contentType = this.contentType;
|
||||||
|
|
||||||
|
if (!contentType)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (contentType.indexOf("text/") == 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (NetworkHelper.mimeCategoryMap[contentType]) {
|
||||||
|
case "txt":
|
||||||
|
case "js":
|
||||||
|
case "json":
|
||||||
|
case "css":
|
||||||
|
case "html":
|
||||||
|
case "svg":
|
||||||
|
case "xml":
|
||||||
|
return true;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tells if the server response is cached.
|
||||||
|
*
|
||||||
|
* @returns boolean
|
||||||
|
* Returns true if the server responded that the request is already
|
||||||
|
* in the browser's cache, false otherwise.
|
||||||
|
*/
|
||||||
|
get _isResponseCached()
|
||||||
|
{
|
||||||
|
return this.httpActivity.log.entries[0].response.status == 304;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tells if the request body includes form data.
|
||||||
|
*
|
||||||
|
* @returns boolean
|
||||||
|
* Returns true if the posted body contains form data.
|
||||||
|
*/
|
||||||
|
get _isRequestBodyFormData()
|
||||||
|
{
|
||||||
|
let requestBody = this.httpActivity.log.entries[0].request.postData.text;
|
||||||
|
return this._fromDataRegExp.test(requestBody);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Appends the node with id=aId by the text aValue.
|
||||||
|
*
|
||||||
|
* @param string aId
|
||||||
|
* @param string aValue
|
||||||
|
* @returns void
|
||||||
|
*/
|
||||||
|
_appendTextNode: function NP_appendTextNode(aId, aValue)
|
||||||
|
{
|
||||||
|
let textNode = this.document.createTextNode(aValue);
|
||||||
|
this.document.getElementById(aId).appendChild(textNode);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates some HTML to display the key-value pair of the aList data. The
|
||||||
|
* generated HTML is added to node with id=aParentId.
|
||||||
|
*
|
||||||
|
* @param string aParentId
|
||||||
|
* Id of the parent node to append the list to.
|
||||||
|
* @oaram array aList
|
||||||
|
* Array that holds the objects you want to display. Each object must
|
||||||
|
* have two properties: name and value.
|
||||||
|
* @param boolean aIgnoreCookie
|
||||||
|
* If true, the key-value named "Cookie" is not added to the list.
|
||||||
|
* @returns void
|
||||||
|
*/
|
||||||
|
_appendList: function NP_appendList(aParentId, aList, aIgnoreCookie)
|
||||||
|
{
|
||||||
|
let parent = this.document.getElementById(aParentId);
|
||||||
|
let doc = this.document;
|
||||||
|
|
||||||
|
aList.sort(function(a, b) {
|
||||||
|
return a.name.toLowerCase() < b.name.toLowerCase();
|
||||||
|
});
|
||||||
|
|
||||||
|
aList.forEach(function(aItem) {
|
||||||
|
let name = aItem.name;
|
||||||
|
let value = aItem.value;
|
||||||
|
if (aIgnoreCookie && name == "Cookie") {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The following code creates the HTML:
|
||||||
|
* <tr>
|
||||||
|
* <th scope="row" class="property-name">${line}:</th>
|
||||||
|
* <td class="property-value">${aList[line]}</td>
|
||||||
|
* </tr>
|
||||||
|
* and adds it to parent.
|
||||||
|
*/
|
||||||
|
let row = doc.createElement("tr");
|
||||||
|
let textNode = doc.createTextNode(name + ":");
|
||||||
|
let th = doc.createElement("th");
|
||||||
|
th.setAttribute("scope", "row");
|
||||||
|
th.setAttribute("class", "property-name");
|
||||||
|
th.appendChild(textNode);
|
||||||
|
row.appendChild(th);
|
||||||
|
|
||||||
|
textNode = doc.createTextNode(value);
|
||||||
|
let td = doc.createElement("td");
|
||||||
|
td.setAttribute("class", "property-value");
|
||||||
|
td.appendChild(textNode);
|
||||||
|
row.appendChild(td);
|
||||||
|
|
||||||
|
parent.appendChild(row);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Displays the node with id=aId.
|
||||||
|
*
|
||||||
|
* @param string aId
|
||||||
|
* @returns void
|
||||||
|
*/
|
||||||
|
_displayNode: function NP_displayNode(aId)
|
||||||
|
{
|
||||||
|
this.document.getElementById(aId).style.display = "block";
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the request URL, request method, the timing information when the
|
||||||
|
* request started and the request header content on the NetworkPanel.
|
||||||
|
* If the request header contains cookie data, a list of sent cookies is
|
||||||
|
* generated and a special sent cookie section is displayed + the cookie list
|
||||||
|
* added to it.
|
||||||
|
*
|
||||||
|
* @returns void
|
||||||
|
*/
|
||||||
|
_displayRequestHeader: function NP__displayRequestHeader()
|
||||||
|
{
|
||||||
|
let entry = this.httpActivity.log.entries[0];
|
||||||
|
let request = entry.request;
|
||||||
|
let requestTime = new Date(entry.startedDateTime);
|
||||||
|
|
||||||
|
this._appendTextNode("headUrl", request.url);
|
||||||
|
this._appendTextNode("headMethod", request.method);
|
||||||
|
this._appendTextNode("requestHeadersInfo",
|
||||||
|
l10n.timestampString(requestTime));
|
||||||
|
|
||||||
|
this._appendList("requestHeadersContent", request.headers, true);
|
||||||
|
|
||||||
|
if (request.cookies.length > 0) {
|
||||||
|
this._displayNode("requestCookie");
|
||||||
|
this._appendList("requestCookieContent", request.cookies);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Displays the request body section of the NetworkPanel and set the request
|
||||||
|
* body content on the NetworkPanel.
|
||||||
|
*
|
||||||
|
* @returns void
|
||||||
|
*/
|
||||||
|
_displayRequestBody: function NP__displayRequestBody() {
|
||||||
|
let postData = this.httpActivity.log.entries[0].request.postData;
|
||||||
|
this._displayNode("requestBody");
|
||||||
|
this._appendTextNode("requestBodyContent", postData.text);
|
||||||
|
},
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Displays the `sent form data` section. Parses the request header for the
|
||||||
|
* submitted form data displays it inside of the `sent form data` section.
|
||||||
|
*
|
||||||
|
* @returns void
|
||||||
|
*/
|
||||||
|
_displayRequestForm: function NP__processRequestForm() {
|
||||||
|
let postData = this.httpActivity.log.entries[0].request.postData.text;
|
||||||
|
let requestBodyLines = postData.split("\n");
|
||||||
|
let formData = requestBodyLines[requestBodyLines.length - 1].
|
||||||
|
replace(/\+/g, " ").split("&");
|
||||||
|
|
||||||
|
function unescapeText(aText)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
return decodeURIComponent(aText);
|
||||||
|
}
|
||||||
|
catch (ex) {
|
||||||
|
return decodeURIComponent(unescape(aText));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let formDataArray = [];
|
||||||
|
for (let i = 0; i < formData.length; i++) {
|
||||||
|
let data = formData[i];
|
||||||
|
let idx = data.indexOf("=");
|
||||||
|
let key = data.substring(0, idx);
|
||||||
|
let value = data.substring(idx + 1);
|
||||||
|
formDataArray.push({
|
||||||
|
name: unescapeText(key),
|
||||||
|
value: unescapeText(value)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
this._appendList("requestFormDataContent", formDataArray);
|
||||||
|
this._displayNode("requestFormData");
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Displays the response section of the NetworkPanel, sets the response status,
|
||||||
|
* the duration between the start of the request and the receiving of the
|
||||||
|
* response header as well as the response header content on the the NetworkPanel.
|
||||||
|
*
|
||||||
|
* @returns void
|
||||||
|
*/
|
||||||
|
_displayResponseHeader: function NP__displayResponseHeader()
|
||||||
|
{
|
||||||
|
let entry = this.httpActivity.log.entries[0];
|
||||||
|
let timing = entry.timings;
|
||||||
|
let response = entry.response;
|
||||||
|
|
||||||
|
this._appendTextNode("headStatus",
|
||||||
|
[response.httpVersion, response.status,
|
||||||
|
response.statusText].join(" "));
|
||||||
|
|
||||||
|
// Calculate how much time it took from the request start, until the
|
||||||
|
// response started to be received.
|
||||||
|
let deltaDuration = 0;
|
||||||
|
["dns", "connect", "send", "wait"].forEach(function (aValue) {
|
||||||
|
let ms = timing[aValue];
|
||||||
|
if (ms > -1) {
|
||||||
|
deltaDuration += ms;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this._appendTextNode("responseHeadersInfo",
|
||||||
|
this._format("durationMS", [deltaDuration]));
|
||||||
|
|
||||||
|
this._displayNode("responseContainer");
|
||||||
|
this._appendList("responseHeadersContent", response.headers);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Displays the respones image section, sets the source of the image displayed
|
||||||
|
* in the image response section to the request URL and the duration between
|
||||||
|
* the receiving of the response header and the end of the request. Once the
|
||||||
|
* image is loaded, the size of the requested image is set.
|
||||||
|
*
|
||||||
|
* @returns void
|
||||||
|
*/
|
||||||
|
_displayResponseImage: function NP__displayResponseImage()
|
||||||
|
{
|
||||||
|
let self = this;
|
||||||
|
let entry = this.httpActivity.log.entries[0];
|
||||||
|
let timing = entry.timings;
|
||||||
|
let request = entry.request;
|
||||||
|
let cached = "";
|
||||||
|
|
||||||
|
if (this._isResponseCached) {
|
||||||
|
cached = "Cached";
|
||||||
|
}
|
||||||
|
|
||||||
|
let imageNode = this.document.getElementById("responseImage" + cached +"Node");
|
||||||
|
imageNode.setAttribute("src", request.url);
|
||||||
|
|
||||||
|
// This function is called to set the imageInfo.
|
||||||
|
function setImageInfo() {
|
||||||
|
self._appendTextNode("responseImage" + cached + "Info",
|
||||||
|
self._format("imageSizeDeltaDurationMS",
|
||||||
|
[ imageNode.width, imageNode.height, timing.receive ]
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the image is already loaded.
|
||||||
|
if (imageNode.width != 0) {
|
||||||
|
setImageInfo();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Image is not loaded yet therefore add a load event.
|
||||||
|
imageNode.addEventListener("load", function imageNodeLoad() {
|
||||||
|
imageNode.removeEventListener("load", imageNodeLoad, false);
|
||||||
|
setImageInfo();
|
||||||
|
}, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
this._displayNode("responseImage" + cached);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Displays the response body section, sets the the duration between
|
||||||
|
* the receiving of the response header and the end of the request as well as
|
||||||
|
* the content of the response body on the NetworkPanel.
|
||||||
|
*
|
||||||
|
* @returns void
|
||||||
|
*/
|
||||||
|
_displayResponseBody: function NP__displayResponseBody()
|
||||||
|
{
|
||||||
|
let entry = this.httpActivity.log.entries[0];
|
||||||
|
let timing = entry.timings;
|
||||||
|
let response = entry.response;
|
||||||
|
let cached = this._isResponseCached ? "Cached" : "";
|
||||||
|
|
||||||
|
this._appendTextNode("responseBody" + cached + "Info",
|
||||||
|
this._format("durationMS", [timing.receive]));
|
||||||
|
|
||||||
|
this._displayNode("responseBody" + cached);
|
||||||
|
this._appendTextNode("responseBody" + cached + "Content",
|
||||||
|
response.content.text);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Displays the `Unknown Content-Type hint` and sets the duration between the
|
||||||
|
* receiving of the response header on the NetworkPanel.
|
||||||
|
*
|
||||||
|
* @returns void
|
||||||
|
*/
|
||||||
|
_displayResponseBodyUnknownType: function NP__displayResponseBodyUnknownType()
|
||||||
|
{
|
||||||
|
let timing = this.httpActivity.log.entries[0].timings;
|
||||||
|
|
||||||
|
this._displayNode("responseBodyUnknownType");
|
||||||
|
this._appendTextNode("responseBodyUnknownTypeInfo",
|
||||||
|
this._format("durationMS", [timing.receive]));
|
||||||
|
|
||||||
|
this._appendTextNode("responseBodyUnknownTypeContent",
|
||||||
|
this._format("responseBodyUnableToDisplay.content", [this.contentType]));
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Displays the `no response body` section and sets the the duration between
|
||||||
|
* the receiving of the response header and the end of the request.
|
||||||
|
*
|
||||||
|
* @returns void
|
||||||
|
*/
|
||||||
|
_displayNoResponseBody: function NP_displayNoResponseBody()
|
||||||
|
{
|
||||||
|
let timing = this.httpActivity.log.entries[0].timings;
|
||||||
|
|
||||||
|
this._displayNode("responseNoBody");
|
||||||
|
this._appendTextNode("responseNoBodyInfo",
|
||||||
|
this._format("durationMS", [timing.receive]));
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the content of the NetworkPanel's iframe.
|
||||||
|
*
|
||||||
|
* @returns void
|
||||||
|
*/
|
||||||
|
update: function NP_update()
|
||||||
|
{
|
||||||
|
// 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) {
|
||||||
|
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;
|
||||||
|
|
||||||
|
switch (this._state) {
|
||||||
|
case this._INIT:
|
||||||
|
this._displayRequestHeader();
|
||||||
|
this._state = this._DISPLAYED_REQUEST_HEADER;
|
||||||
|
// FALL THROUGH
|
||||||
|
|
||||||
|
case this._DISPLAYED_REQUEST_HEADER:
|
||||||
|
// Process the request body if there is one.
|
||||||
|
if (!this.httpActivity.meta.discardRequestBody && request.postData) {
|
||||||
|
// Check if we send some form data. If so, display the form data special.
|
||||||
|
if (this._isRequestBodyFormData) {
|
||||||
|
this._displayRequestForm();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this._displayRequestBody();
|
||||||
|
}
|
||||||
|
this._state = this._DISPLAYED_REQUEST_BODY;
|
||||||
|
}
|
||||||
|
// 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;
|
||||||
|
}
|
||||||
|
this._displayResponseHeader();
|
||||||
|
this._state = this._DISPLAYED_RESPONSE_HEADER;
|
||||||
|
// FALL THROUGH
|
||||||
|
|
||||||
|
case this._DISPLAYED_RESPONSE_HEADER:
|
||||||
|
if (stages.indexOf("REQUEST_STOP") == -1 ||
|
||||||
|
stages.indexOf("TRANSACTION_CLOSE") == -1) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
this._state = this._TRANSITION_CLOSED;
|
||||||
|
if (this.httpActivity.meta.discardResponseBody) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!response.content || !response.content.text) {
|
||||||
|
this._displayNoResponseBody();
|
||||||
|
}
|
||||||
|
else if (this._responseIsImage) {
|
||||||
|
this._displayResponseImage();
|
||||||
|
}
|
||||||
|
else if (!this._isResponseBodyTextData) {
|
||||||
|
this._displayResponseBodyUnknownType();
|
||||||
|
}
|
||||||
|
else if (response.content.text) {
|
||||||
|
this._displayResponseBody();
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a DOMNode and sets all the attributes of aAttributes on the created
|
||||||
|
* element.
|
||||||
|
*
|
||||||
|
* @param nsIDOMDocument aDocument
|
||||||
|
* Document to create the new DOMNode.
|
||||||
|
* @param string aTag
|
||||||
|
* Name of the tag for the DOMNode.
|
||||||
|
* @param object aAttributes
|
||||||
|
* Attributes set on the created DOMNode.
|
||||||
|
*
|
||||||
|
* @returns nsIDOMNode
|
||||||
|
*/
|
||||||
|
function createElement(aDocument, aTag, aAttributes)
|
||||||
|
{
|
||||||
|
let node = aDocument.createElement(aTag);
|
||||||
|
if (aAttributes) {
|
||||||
|
for (let attr in aAttributes) {
|
||||||
|
node.setAttribute(attr, aAttributes[attr]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new DOMNode and appends it to aParent.
|
||||||
|
*
|
||||||
|
* @param nsIDOMNode aParent
|
||||||
|
* A parent node to append the created element.
|
||||||
|
* @param string aTag
|
||||||
|
* Name of the tag for the DOMNode.
|
||||||
|
* @param object aAttributes
|
||||||
|
* Attributes set on the created DOMNode.
|
||||||
|
*
|
||||||
|
* @returns nsIDOMNode
|
||||||
|
*/
|
||||||
|
function createAndAppendElement(aParent, aTag, aAttributes)
|
||||||
|
{
|
||||||
|
let node = createElement(aParent.ownerDocument, aTag, aAttributes);
|
||||||
|
aParent.appendChild(node);
|
||||||
|
return node;
|
||||||
|
}
|
|
@ -11,17 +11,12 @@ const Ci = Components.interfaces;
|
||||||
const Cu = Components.utils;
|
const Cu = Components.utils;
|
||||||
|
|
||||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||||
Cu.import("resource://gre/modules/Services.jsm");
|
|
||||||
|
|
||||||
XPCOMUtils.defineLazyGetter(this, "WebConsoleUtils", function () {
|
XPCOMUtils.defineLazyModuleGetter(this, "WebConsoleUtils",
|
||||||
let obj = {};
|
"resource:///modules/WebConsoleUtils.jsm");
|
||||||
Cu.import("resource:///modules/WebConsoleUtils.jsm", obj);
|
|
||||||
return obj.WebConsoleUtils;
|
|
||||||
});
|
|
||||||
|
|
||||||
var EXPORTED_SYMBOLS = ["PropertyPanel", "PropertyTreeView"];
|
var EXPORTED_SYMBOLS = ["PropertyPanel", "PropertyTreeView"];
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
//// PropertyTreeView.
|
//// PropertyTreeView.
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,9 @@ const Ci = Components.interfaces;
|
||||||
const Cu = Components.utils;
|
const Cu = Components.utils;
|
||||||
|
|
||||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||||
Cu.import("resource://gre/modules/Services.jsm");
|
|
||||||
|
XPCOMUtils.defineLazyModuleGetter(this, "Services",
|
||||||
|
"resource://gre/modules/Services.jsm");
|
||||||
|
|
||||||
var EXPORTED_SYMBOLS = ["WebConsoleUtils", "JSPropertyProvider"];
|
var EXPORTED_SYMBOLS = ["WebConsoleUtils", "JSPropertyProvider"];
|
||||||
|
|
||||||
|
|
|
@ -5,31 +5,17 @@
|
||||||
|
|
||||||
const TEST_FILE = "test-network.html";
|
const TEST_FILE = "test-network.html";
|
||||||
|
|
||||||
function tabLoad(aEvent) {
|
|
||||||
browser.removeEventListener(aEvent.type, arguments.callee, true);
|
|
||||||
|
|
||||||
openConsole();
|
|
||||||
|
|
||||||
let hudId = HUDService.getHudIdByWindow(content);
|
|
||||||
hud = HUDService.hudReferences[hudId];
|
|
||||||
|
|
||||||
browser.addEventListener("load", tabReload, true);
|
|
||||||
|
|
||||||
content.location.reload();
|
|
||||||
}
|
|
||||||
|
|
||||||
function tabReload(aEvent) {
|
function tabReload(aEvent) {
|
||||||
browser.removeEventListener(aEvent.type, arguments.callee, true);
|
browser.removeEventListener(aEvent.type, tabReload, true);
|
||||||
|
|
||||||
let textContent = hud.outputNode.textContent;
|
outputNode = hud.outputNode;
|
||||||
isnot(textContent.indexOf("test-network.html"), -1,
|
findLogEntry("test-network.html");
|
||||||
"found test-network.html");
|
findLogEntry("test-image.png");
|
||||||
isnot(textContent.indexOf("test-image.png"), -1, "found test-image.png");
|
findLogEntry("testscript.js");
|
||||||
isnot(textContent.indexOf("testscript.js"), -1, "found testscript.js");
|
isnot(outputNode.textContent.indexOf("running network console logging tests"), -1,
|
||||||
isnot(textContent.indexOf("running network console logging tests"), -1,
|
|
||||||
"found the console.log() message from testscript.js");
|
"found the console.log() message from testscript.js");
|
||||||
|
|
||||||
finishTest();
|
executeSoon(finishTest);
|
||||||
}
|
}
|
||||||
|
|
||||||
function test() {
|
function test() {
|
||||||
|
@ -42,5 +28,12 @@ function test() {
|
||||||
let uri = Services.io.newFileURI(dir);
|
let uri = Services.io.newFileURI(dir);
|
||||||
|
|
||||||
addTab(uri.spec);
|
addTab(uri.spec);
|
||||||
browser.addEventListener("load", tabLoad, true);
|
browser.addEventListener("load", function tabLoad() {
|
||||||
|
browser.removeEventListener("load", tabLoad, true);
|
||||||
|
openConsole(null, function(aHud) {
|
||||||
|
hud = aHud;
|
||||||
|
browser.addEventListener("load", tabReload, true);
|
||||||
|
content.location.reload();
|
||||||
|
});
|
||||||
|
}, true);
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,25 +10,27 @@
|
||||||
|
|
||||||
const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/test-bug-599725-response-headers.sjs";
|
const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/test-bug-599725-response-headers.sjs";
|
||||||
|
|
||||||
let lastFinishedRequest = null;
|
function performTest(lastFinishedRequest)
|
||||||
|
|
||||||
function requestDoneCallback(aHttpRequest)
|
|
||||||
{
|
|
||||||
lastFinishedRequest = aHttpRequest;
|
|
||||||
}
|
|
||||||
|
|
||||||
function performTest()
|
|
||||||
{
|
{
|
||||||
ok(lastFinishedRequest, "page load was logged");
|
ok(lastFinishedRequest, "page load was logged");
|
||||||
|
|
||||||
let headers = lastFinishedRequest.response.header;
|
function readHeader(aName)
|
||||||
ok(headers, "we have the response headers");
|
{
|
||||||
ok(!headers["Content-Type"], "we do not have the Content-Type header");
|
for (let header of headers) {
|
||||||
ok(headers["Content-Length"] != 60, "Content-Length != 60");
|
if (header.name == aName) {
|
||||||
|
return header.value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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");
|
||||||
|
|
||||||
lastFinishedRequest = null;
|
|
||||||
HUDService.lastFinishedRequestCallback = null;
|
HUDService.lastFinishedRequestCallback = null;
|
||||||
finishTest();
|
executeSoon(finishTest);
|
||||||
}
|
}
|
||||||
|
|
||||||
function test()
|
function test()
|
||||||
|
@ -37,15 +39,15 @@ function test()
|
||||||
|
|
||||||
let initialLoad = true;
|
let initialLoad = true;
|
||||||
|
|
||||||
browser.addEventListener("load", function () {
|
browser.addEventListener("load", function onLoad() {
|
||||||
if (initialLoad) {
|
if (initialLoad) {
|
||||||
openConsole();
|
openConsole(null, function() {
|
||||||
HUDService.lastFinishedRequestCallback = requestDoneCallback;
|
HUDService.lastFinishedRequestCallback = performTest;
|
||||||
content.location.reload();
|
content.location.reload();
|
||||||
|
});
|
||||||
initialLoad = false;
|
initialLoad = false;
|
||||||
} else {
|
} else {
|
||||||
browser.removeEventListener("load", arguments.callee, true);
|
browser.removeEventListener("load", onLoad, true);
|
||||||
performTest();
|
|
||||||
}
|
}
|
||||||
}, true);
|
}, true);
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,28 +10,19 @@
|
||||||
|
|
||||||
const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/test-bug-600183-charset.html";
|
const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/test-bug-600183-charset.html";
|
||||||
|
|
||||||
let lastFinishedRequest = null;
|
function performTest(lastFinishedRequest)
|
||||||
|
|
||||||
function requestDoneCallback(aHttpRequest)
|
|
||||||
{
|
|
||||||
lastFinishedRequest = aHttpRequest;
|
|
||||||
}
|
|
||||||
|
|
||||||
function performTest()
|
|
||||||
{
|
{
|
||||||
ok(lastFinishedRequest, "charset test page was loaded and logged");
|
ok(lastFinishedRequest, "charset test page was loaded and logged");
|
||||||
|
|
||||||
let body = lastFinishedRequest.response.body;
|
let body = lastFinishedRequest.log.entries[0].response.content.text;
|
||||||
ok(body, "we have the response body");
|
ok(body, "we have the response body");
|
||||||
|
|
||||||
let chars = "\u7684\u95ee\u5019!"; // 的问候!
|
let chars = "\u7684\u95ee\u5019!"; // 的问候!
|
||||||
isnot(body.indexOf("<p>" + chars + "</p>"), -1,
|
isnot(body.indexOf("<p>" + chars + "</p>"), -1,
|
||||||
"found the chinese simplified string");
|
"found the chinese simplified string");
|
||||||
|
|
||||||
lastFinishedRequest = null;
|
|
||||||
HUDService.saveRequestAndResponseBodies = false;
|
|
||||||
HUDService.lastFinishedRequestCallback = null;
|
HUDService.lastFinishedRequestCallback = null;
|
||||||
finishTest();
|
executeSoon(finishTest);
|
||||||
}
|
}
|
||||||
|
|
||||||
function test()
|
function test()
|
||||||
|
@ -40,20 +31,18 @@ function test()
|
||||||
|
|
||||||
let initialLoad = true;
|
let initialLoad = true;
|
||||||
|
|
||||||
browser.addEventListener("load", function () {
|
browser.addEventListener("load", function onLoad() {
|
||||||
if (initialLoad) {
|
if (initialLoad) {
|
||||||
waitForFocus(function() {
|
openConsole(null, function(hud) {
|
||||||
openConsole();
|
|
||||||
|
|
||||||
HUDService.saveRequestAndResponseBodies = true;
|
hud.saveRequestAndResponseBodies = true;
|
||||||
HUDService.lastFinishedRequestCallback = requestDoneCallback;
|
HUDService.lastFinishedRequestCallback = performTest;
|
||||||
|
|
||||||
content.location = TEST_URI;
|
content.location = TEST_URI;
|
||||||
}, content);
|
});
|
||||||
initialLoad = false;
|
initialLoad = false;
|
||||||
} else {
|
} else {
|
||||||
browser.removeEventListener("load", arguments.callee, true);
|
browser.removeEventListener("load", onLoad, true);
|
||||||
performTest();
|
|
||||||
}
|
}
|
||||||
}, true);
|
}, true);
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,10 +57,10 @@ function onpopupshown2(aEvent)
|
||||||
isnot(menuitems[1].getAttribute("checked"), "true",
|
isnot(menuitems[1].getAttribute("checked"), "true",
|
||||||
"menuitems[1] is not checked");
|
"menuitems[1] is not checked");
|
||||||
|
|
||||||
ok(!HUDService.saveRequestAndResponseBodies, "bodies are not logged");
|
ok(!huds[1].saveRequestAndResponseBodies, "bodies are not logged");
|
||||||
|
|
||||||
// Enable body logging.
|
// Enable body logging.
|
||||||
HUDService.saveRequestAndResponseBodies = true;
|
huds[1].saveRequestAndResponseBodies = true;
|
||||||
|
|
||||||
menupopups[1].addEventListener("popuphidden", function _onhidden(aEvent) {
|
menupopups[1].addEventListener("popuphidden", function _onhidden(aEvent) {
|
||||||
menupopups[1].removeEventListener(aEvent.type, _onhidden, false);
|
menupopups[1].removeEventListener(aEvent.type, _onhidden, false);
|
||||||
|
@ -103,11 +103,12 @@ function onpopupshown1(aEvent)
|
||||||
{
|
{
|
||||||
menupopups[0].removeEventListener(aEvent.type, onpopupshown1, false);
|
menupopups[0].removeEventListener(aEvent.type, onpopupshown1, false);
|
||||||
|
|
||||||
// The menuitem checkbox must be in sync with the other tabs.
|
// The menuitem checkbox must not be in sync with the other tabs.
|
||||||
is(menuitems[0].getAttribute("checked"), "true", "menuitems[0] is checked");
|
isnot(menuitems[0].getAttribute("checked"), "true",
|
||||||
|
"menuitems[0] is not checked");
|
||||||
|
|
||||||
// Disable body logging.
|
// Enable body logging for tab 1 as well.
|
||||||
HUDService.saveRequestAndResponseBodies = false;
|
huds[0].saveRequestAndResponseBodies = true;
|
||||||
|
|
||||||
// Close the menu, and switch back to tab 2.
|
// Close the menu, and switch back to tab 2.
|
||||||
menupopups[0].addEventListener("popuphidden", function _onhidden(aEvent) {
|
menupopups[0].addEventListener("popuphidden", function _onhidden(aEvent) {
|
||||||
|
@ -127,8 +128,7 @@ function onpopupshown2c(aEvent)
|
||||||
{
|
{
|
||||||
menupopups[1].removeEventListener(aEvent.type, onpopupshown2c, false);
|
menupopups[1].removeEventListener(aEvent.type, onpopupshown2c, false);
|
||||||
|
|
||||||
isnot(menuitems[1].getAttribute("checked"), "true",
|
is(menuitems[1].getAttribute("checked"), "true", "menuitems[1] is checked");
|
||||||
"menuitems[1] is not checked");
|
|
||||||
|
|
||||||
menupopups[1].addEventListener("popuphidden", function _onhidden(aEvent) {
|
menupopups[1].addEventListener("popuphidden", function _onhidden(aEvent) {
|
||||||
menupopups[1].removeEventListener(aEvent.type, _onhidden, false);
|
menupopups[1].removeEventListener(aEvent.type, _onhidden, false);
|
||||||
|
|
|
@ -41,14 +41,11 @@ let TestObserver = {
|
||||||
function tabLoad(aEvent) {
|
function tabLoad(aEvent) {
|
||||||
browser.removeEventListener(aEvent.type, tabLoad, true);
|
browser.removeEventListener(aEvent.type, tabLoad, true);
|
||||||
|
|
||||||
openConsole();
|
openConsole(null, function(aHud) {
|
||||||
|
hud = aHud;
|
||||||
let hudId = HUDService.getHudIdByWindow(content);
|
|
||||||
hud = HUDService.hudReferences[hudId];
|
|
||||||
|
|
||||||
Services.console.registerListener(TestObserver);
|
Services.console.registerListener(TestObserver);
|
||||||
|
|
||||||
content.location = TEST_URI;
|
content.location = TEST_URI;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function performTest() {
|
function performTest() {
|
||||||
|
|
|
@ -92,8 +92,8 @@ function tabLoaded() {
|
||||||
successFn: function()
|
successFn: function()
|
||||||
{
|
{
|
||||||
let jstermMessage = HUD.outputNode.querySelector(".webconsole-msg-output");
|
let jstermMessage = HUD.outputNode.querySelector(".webconsole-msg-output");
|
||||||
EventUtils.synthesizeMouse(networkLink, 2, 2, {});
|
|
||||||
EventUtils.synthesizeMouse(jstermMessage, 2, 2, {});
|
EventUtils.synthesizeMouse(jstermMessage, 2, 2, {});
|
||||||
|
EventUtils.synthesizeMouse(networkLink, 2, 2, {});
|
||||||
},
|
},
|
||||||
failureFn: finishTest,
|
failureFn: finishTest,
|
||||||
});
|
});
|
||||||
|
|
|
@ -118,8 +118,8 @@ function tabLoaded() {
|
||||||
successFn: function()
|
successFn: function()
|
||||||
{
|
{
|
||||||
let jstermMessage = HUD.outputNode.querySelector(".webconsole-msg-output");
|
let jstermMessage = HUD.outputNode.querySelector(".webconsole-msg-output");
|
||||||
EventUtils.synthesizeMouse(networkLink, 2, 2, {});
|
|
||||||
EventUtils.synthesizeMouse(jstermMessage, 2, 2, {});
|
EventUtils.synthesizeMouse(jstermMessage, 2, 2, {});
|
||||||
|
EventUtils.synthesizeMouse(networkLink, 2, 2, {});
|
||||||
},
|
},
|
||||||
failureFn: finishTest,
|
failureFn: finishTest,
|
||||||
});
|
});
|
||||||
|
|
|
@ -13,57 +13,63 @@ let lastFinishedRequests = {};
|
||||||
|
|
||||||
function requestDoneCallback(aHttpRequest)
|
function requestDoneCallback(aHttpRequest)
|
||||||
{
|
{
|
||||||
let status = aHttpRequest.response.status.
|
let status = aHttpRequest.log.entries[0].response.status;
|
||||||
replace(/^HTTP\/\d\.\d (\d+).+$/, "$1");
|
|
||||||
lastFinishedRequests[status] = aHttpRequest;
|
lastFinishedRequests[status] = aHttpRequest;
|
||||||
}
|
}
|
||||||
|
|
||||||
function performTest(aEvent)
|
function performTest(aEvent)
|
||||||
{
|
{
|
||||||
HUDService.saveRequestAndResponseBodies = false;
|
|
||||||
HUDService.lastFinishedRequestCallback = null;
|
HUDService.lastFinishedRequestCallback = null;
|
||||||
|
|
||||||
ok("301" in lastFinishedRequests, "request 1: 301 Moved Permanently");
|
ok("301" in lastFinishedRequests, "request 1: 301 Moved Permanently");
|
||||||
ok("404" in lastFinishedRequests, "request 2: 404 Not found");
|
ok("404" in lastFinishedRequests, "request 2: 404 Not found");
|
||||||
|
|
||||||
let headers0 = lastFinishedRequests["301"].response.header;
|
function readHeader(aName)
|
||||||
is(headers0["Content-Type"], "text/html",
|
{
|
||||||
|
for (let header of headers) {
|
||||||
|
if (header.name == aName) {
|
||||||
|
return header.value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
let headers = lastFinishedRequests["301"].log.entries[0].response.headers;
|
||||||
|
is(readHeader("Content-Type"), "text/html",
|
||||||
"we do have the Content-Type header");
|
"we do have the Content-Type header");
|
||||||
is(headers0["Content-Length"], 71, "Content-Length is correct");
|
is(readHeader("Content-Length"), 71, "Content-Length is correct");
|
||||||
is(headers0["Location"], "/redirect-from-bug-630733",
|
is(readHeader("Location"), "/redirect-from-bug-630733",
|
||||||
"Content-Length is correct");
|
"Content-Length is correct");
|
||||||
is(headers0["x-foobar-bug630733"], "bazbaz",
|
is(readHeader("x-foobar-bug630733"), "bazbaz",
|
||||||
"X-Foobar-bug630733 is correct");
|
"X-Foobar-bug630733 is correct");
|
||||||
let body = lastFinishedRequests["301"].response.body;
|
let body = lastFinishedRequests["301"].log.entries[0].response.content;
|
||||||
ok(!body, "body discarded for request 1");
|
ok(!body.text, "body discarded for request 1");
|
||||||
|
|
||||||
let headers1 = lastFinishedRequests["404"].response.header;
|
headers = lastFinishedRequests["404"].log.entries[0].response.headers;
|
||||||
ok(!headers1["Location"], "no Location header");
|
ok(!readHeader("Location"), "no Location header");
|
||||||
ok(!headers1["x-foobar-bug630733"], "no X-Foobar-bug630733 header");
|
ok(!readHeader("x-foobar-bug630733"), "no X-Foobar-bug630733 header");
|
||||||
|
|
||||||
body = lastFinishedRequests["404"].response.body;
|
body = lastFinishedRequests["404"].log.entries[0].response.content.text;
|
||||||
isnot(body.indexOf("404"), -1,
|
isnot(body.indexOf("404"), -1,
|
||||||
"body is correct for request 2");
|
"body is correct for request 2");
|
||||||
|
|
||||||
lastFinishedRequests = null;
|
lastFinishedRequests = null;
|
||||||
finishTest();
|
executeSoon(finishTest);
|
||||||
}
|
}
|
||||||
|
|
||||||
function test()
|
function test()
|
||||||
{
|
{
|
||||||
addTab("data:text/html;charset=utf-8,<p>Web Console test for bug 630733");
|
addTab("data:text/html;charset=utf-8,<p>Web Console test for bug 630733");
|
||||||
|
|
||||||
browser.addEventListener("load", function(aEvent) {
|
browser.addEventListener("load", function onLoad1(aEvent) {
|
||||||
browser.removeEventListener(aEvent.type, arguments.callee, true);
|
browser.removeEventListener(aEvent.type, onLoad1, true);
|
||||||
|
|
||||||
executeSoon(function() {
|
openConsole(null, function(hud) {
|
||||||
openConsole();
|
hud.saveRequestAndResponseBodies = true;
|
||||||
|
|
||||||
HUDService.saveRequestAndResponseBodies = true;
|
|
||||||
HUDService.lastFinishedRequestCallback = requestDoneCallback;
|
HUDService.lastFinishedRequestCallback = requestDoneCallback;
|
||||||
|
|
||||||
browser.addEventListener("load", function(aEvent) {
|
browser.addEventListener("load", function onLoad2(aEvent) {
|
||||||
browser.removeEventListener(aEvent.type, arguments.callee, true);
|
browser.removeEventListener(aEvent.type, onLoad2, true);
|
||||||
executeSoon(performTest);
|
executeSoon(performTest);
|
||||||
}, true);
|
}, true);
|
||||||
|
|
||||||
|
|
|
@ -18,38 +18,36 @@ function test()
|
||||||
{
|
{
|
||||||
addTab("data:text/html;charset=utf-8,Web Console network logging tests");
|
addTab("data:text/html;charset=utf-8,Web Console network logging tests");
|
||||||
|
|
||||||
browser.addEventListener("load", function() {
|
browser.addEventListener("load", function onLoad() {
|
||||||
browser.removeEventListener("load", arguments.callee, true);
|
browser.removeEventListener("load", onLoad, true);
|
||||||
|
|
||||||
openConsole();
|
openConsole(null, function(aHud) {
|
||||||
|
hud = aHud;
|
||||||
hud = HUDService.getHudByWindow(content);
|
|
||||||
ok(hud, "Web Console is now open");
|
|
||||||
|
|
||||||
HUDService.lastFinishedRequestCallback = function(aRequest) {
|
HUDService.lastFinishedRequestCallback = function(aRequest) {
|
||||||
lastRequest = aRequest;
|
lastRequest = aRequest.log.entries[0];
|
||||||
if (requestCallback) {
|
if (requestCallback) {
|
||||||
requestCallback();
|
requestCallback();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
executeSoon(testPageLoad);
|
executeSoon(testPageLoad);
|
||||||
|
});
|
||||||
}, true);
|
}, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testPageLoad()
|
function testPageLoad()
|
||||||
{
|
{
|
||||||
browser.addEventListener("load", function(aEvent) {
|
requestCallback = function() {
|
||||||
browser.removeEventListener(aEvent.type, arguments.callee, true);
|
|
||||||
|
|
||||||
// Check if page load was logged correctly.
|
// Check if page load was logged correctly.
|
||||||
ok(lastRequest, "Page load was logged");
|
ok(lastRequest, "Page load was logged");
|
||||||
is(lastRequest.url, TEST_NETWORK_REQUEST_URI,
|
is(lastRequest.request.url, TEST_NETWORK_REQUEST_URI,
|
||||||
"Logged network entry is page load");
|
"Logged network entry is page load");
|
||||||
is(lastRequest.method, "GET", "Method is correct");
|
is(lastRequest.request.method, "GET", "Method is correct");
|
||||||
lastRequest = null;
|
lastRequest = null;
|
||||||
|
requestCallback = null;
|
||||||
executeSoon(testPageLoadBody);
|
executeSoon(testPageLoadBody);
|
||||||
}, true);
|
};
|
||||||
|
|
||||||
content.location = TEST_NETWORK_REQUEST_URI;
|
content.location = TEST_NETWORK_REQUEST_URI;
|
||||||
}
|
}
|
||||||
|
@ -57,12 +55,12 @@ function testPageLoad()
|
||||||
function testPageLoadBody()
|
function testPageLoadBody()
|
||||||
{
|
{
|
||||||
// Turn off logging of request bodies and check again.
|
// Turn off logging of request bodies and check again.
|
||||||
browser.addEventListener("load", function(aEvent) {
|
requestCallback = function() {
|
||||||
browser.removeEventListener(aEvent.type, arguments.callee, true);
|
|
||||||
ok(lastRequest, "Page load was logged again");
|
ok(lastRequest, "Page load was logged again");
|
||||||
lastRequest = null;
|
lastRequest = null;
|
||||||
|
requestCallback = null;
|
||||||
executeSoon(testXhrGet);
|
executeSoon(testXhrGet);
|
||||||
}, true);
|
};
|
||||||
|
|
||||||
content.location.reload();
|
content.location.reload();
|
||||||
}
|
}
|
||||||
|
@ -71,7 +69,7 @@ function testXhrGet()
|
||||||
{
|
{
|
||||||
requestCallback = function() {
|
requestCallback = function() {
|
||||||
ok(lastRequest, "testXhrGet() was logged");
|
ok(lastRequest, "testXhrGet() was logged");
|
||||||
is(lastRequest.method, "GET", "Method is correct");
|
is(lastRequest.request.method, "GET", "Method is correct");
|
||||||
lastRequest = null;
|
lastRequest = null;
|
||||||
requestCallback = null;
|
requestCallback = null;
|
||||||
executeSoon(testXhrPost);
|
executeSoon(testXhrPost);
|
||||||
|
@ -85,7 +83,7 @@ function testXhrPost()
|
||||||
{
|
{
|
||||||
requestCallback = function() {
|
requestCallback = function() {
|
||||||
ok(lastRequest, "testXhrPost() was logged");
|
ok(lastRequest, "testXhrPost() was logged");
|
||||||
is(lastRequest.method, "POST", "Method is correct");
|
is(lastRequest.request.method, "POST", "Method is correct");
|
||||||
lastRequest = null;
|
lastRequest = null;
|
||||||
requestCallback = null;
|
requestCallback = null;
|
||||||
executeSoon(testFormSubmission);
|
executeSoon(testFormSubmission);
|
||||||
|
@ -99,12 +97,11 @@ function testFormSubmission()
|
||||||
{
|
{
|
||||||
// Start the form submission test. As the form is submitted, the page is
|
// Start the form submission test. As the form is submitted, the page is
|
||||||
// loaded again. Bind to the load event to catch when this is done.
|
// loaded again. Bind to the load event to catch when this is done.
|
||||||
browser.addEventListener("load", function(aEvent) {
|
requestCallback = function() {
|
||||||
browser.removeEventListener(aEvent.type, arguments.callee, true);
|
|
||||||
ok(lastRequest, "testFormSubmission() was logged");
|
ok(lastRequest, "testFormSubmission() was logged");
|
||||||
is(lastRequest.method, "POST", "Method is correct");
|
is(lastRequest.request.method, "POST", "Method is correct");
|
||||||
executeSoon(testLiveFilteringOnSearchStrings);
|
executeSoon(testLiveFilteringOnSearchStrings);
|
||||||
}, true);
|
};
|
||||||
|
|
||||||
let form = content.document.querySelector("form");
|
let form = content.document.querySelector("form");
|
||||||
ok(form, "we have the HTML form");
|
ok(form, "we have the HTML form");
|
||||||
|
@ -112,9 +109,6 @@ function testFormSubmission()
|
||||||
}
|
}
|
||||||
|
|
||||||
function testLiveFilteringOnSearchStrings() {
|
function testLiveFilteringOnSearchStrings() {
|
||||||
browser.removeEventListener("DOMContentLoaded",
|
|
||||||
testLiveFilteringOnSearchStrings, false);
|
|
||||||
|
|
||||||
setStringFilter("http");
|
setStringFilter("http");
|
||||||
isnot(countMessageNodes(), 0, "the log nodes are not hidden when the " +
|
isnot(countMessageNodes(), 0, "the log nodes are not hidden when the " +
|
||||||
"search string is set to \"http\"");
|
"search string is set to \"http\"");
|
||||||
|
@ -146,6 +140,9 @@ function testLiveFilteringOnSearchStrings() {
|
||||||
is(countMessageNodes(), 0, "the log nodes are hidden when searching for " +
|
is(countMessageNodes(), 0, "the log nodes are hidden when searching for " +
|
||||||
"the string \"foo\"bar'baz\"boo'\"");
|
"the string \"foo\"bar'baz\"boo'\"");
|
||||||
|
|
||||||
|
HUDService.lastFinishedRequestCallback = null;
|
||||||
|
lastRequest = null;
|
||||||
|
requestCallback = null;
|
||||||
finishTest();
|
finishTest();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,47 +21,47 @@ const TEST_DATA_JSON_CONTENT =
|
||||||
|
|
||||||
let lastRequest = null;
|
let lastRequest = null;
|
||||||
let requestCallback = null;
|
let requestCallback = null;
|
||||||
|
let lastActivity = null;
|
||||||
|
|
||||||
function test()
|
function test()
|
||||||
{
|
{
|
||||||
addTab("data:text/html;charset=utf-8,Web Console network logging tests");
|
addTab("data:text/html;charset=utf-8,Web Console network logging tests");
|
||||||
|
|
||||||
browser.addEventListener("load", function() {
|
browser.addEventListener("load", function onLoad() {
|
||||||
browser.removeEventListener("load", arguments.callee, true);
|
browser.removeEventListener("load", onLoad, true);
|
||||||
|
|
||||||
openConsole();
|
openConsole(null, function(aHud) {
|
||||||
|
hud = aHud;
|
||||||
hud = HUDService.getHudByWindow(content);
|
|
||||||
ok(hud, "Web Console is now open");
|
|
||||||
|
|
||||||
HUDService.lastFinishedRequestCallback = function(aRequest) {
|
HUDService.lastFinishedRequestCallback = function(aRequest) {
|
||||||
lastRequest = aRequest;
|
lastRequest = aRequest.log.entries[0];
|
||||||
|
lastActivity = aRequest;
|
||||||
if (requestCallback) {
|
if (requestCallback) {
|
||||||
requestCallback();
|
requestCallback();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
executeSoon(testPageLoad);
|
executeSoon(testPageLoad);
|
||||||
|
});
|
||||||
}, true);
|
}, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testPageLoad()
|
function testPageLoad()
|
||||||
{
|
{
|
||||||
browser.addEventListener("load", function(aEvent) {
|
requestCallback = function() {
|
||||||
browser.removeEventListener(aEvent.type, arguments.callee, true);
|
|
||||||
|
|
||||||
// Check if page load was logged correctly.
|
// Check if page load was logged correctly.
|
||||||
ok(lastRequest, "Page load was logged");
|
ok(lastRequest, "Page load was logged");
|
||||||
is(lastRequest.url, TEST_NETWORK_REQUEST_URI,
|
|
||||||
|
is(lastRequest.request.url, TEST_NETWORK_REQUEST_URI,
|
||||||
"Logged network entry is page load");
|
"Logged network entry is page load");
|
||||||
is(lastRequest.method, "GET", "Method is correct");
|
is(lastRequest.request.method, "GET", "Method is correct");
|
||||||
ok(!("body" in lastRequest.request), "No request body was stored");
|
ok(!lastRequest.request.postData, "No request body was stored");
|
||||||
ok(!("body" in lastRequest.response), "No response body was stored");
|
ok(!lastRequest.response.content.text, "No response body was stored");
|
||||||
ok(!lastRequest.response.listener, "No response listener is stored");
|
|
||||||
|
|
||||||
lastRequest = null;
|
lastRequest = null;
|
||||||
|
requestCallback = null;
|
||||||
executeSoon(testPageLoadBody);
|
executeSoon(testPageLoadBody);
|
||||||
}, true);
|
};
|
||||||
|
|
||||||
content.location = TEST_NETWORK_REQUEST_URI;
|
content.location = TEST_NETWORK_REQUEST_URI;
|
||||||
}
|
}
|
||||||
|
@ -69,17 +69,16 @@ function testPageLoad()
|
||||||
function testPageLoadBody()
|
function testPageLoadBody()
|
||||||
{
|
{
|
||||||
// Turn on logging of request bodies and check again.
|
// Turn on logging of request bodies and check again.
|
||||||
HUDService.saveRequestAndResponseBodies = true;
|
hud.saveRequestAndResponseBodies = true;
|
||||||
browser.addEventListener("load", function(aEvent) {
|
requestCallback = function() {
|
||||||
browser.removeEventListener(aEvent.type, arguments.callee, true);
|
|
||||||
|
|
||||||
ok(lastRequest, "Page load was logged again");
|
ok(lastRequest, "Page load was logged again");
|
||||||
is(lastRequest.response.body.indexOf("<!DOCTYPE HTML>"), 0,
|
is(lastRequest.response.content.text.indexOf("<!DOCTYPE HTML>"), 0,
|
||||||
"Response body's beginning is okay");
|
"Response body's beginning is okay");
|
||||||
|
|
||||||
lastRequest = null;
|
lastRequest = null;
|
||||||
|
requestCallback = null;
|
||||||
executeSoon(testXhrGet);
|
executeSoon(testXhrGet);
|
||||||
}, true);
|
};
|
||||||
|
|
||||||
content.location.reload();
|
content.location.reload();
|
||||||
}
|
}
|
||||||
|
@ -88,9 +87,9 @@ function testXhrGet()
|
||||||
{
|
{
|
||||||
requestCallback = function() {
|
requestCallback = function() {
|
||||||
ok(lastRequest, "testXhrGet() was logged");
|
ok(lastRequest, "testXhrGet() was logged");
|
||||||
is(lastRequest.method, "GET", "Method is correct");
|
is(lastRequest.request.method, "GET", "Method is correct");
|
||||||
is(lastRequest.request.body, null, "No request body was sent");
|
ok(!lastRequest.request.postData, "No request body was sent");
|
||||||
is(lastRequest.response.body, TEST_DATA_JSON_CONTENT,
|
is(lastRequest.response.content.text, TEST_DATA_JSON_CONTENT,
|
||||||
"Response is correct");
|
"Response is correct");
|
||||||
|
|
||||||
lastRequest = null;
|
lastRequest = null;
|
||||||
|
@ -106,10 +105,10 @@ function testXhrPost()
|
||||||
{
|
{
|
||||||
requestCallback = function() {
|
requestCallback = function() {
|
||||||
ok(lastRequest, "testXhrPost() was logged");
|
ok(lastRequest, "testXhrPost() was logged");
|
||||||
is(lastRequest.method, "POST", "Method is correct");
|
is(lastRequest.request.method, "POST", "Method is correct");
|
||||||
is(lastRequest.request.body, "Hello world!",
|
is(lastRequest.request.postData.text, "Hello world!",
|
||||||
"Request body was logged");
|
"Request body was logged");
|
||||||
is(lastRequest.response.body, TEST_DATA_JSON_CONTENT,
|
is(lastRequest.response.content.text, TEST_DATA_JSON_CONTENT,
|
||||||
"Response is correct");
|
"Response is correct");
|
||||||
|
|
||||||
lastRequest = null;
|
lastRequest = null;
|
||||||
|
@ -125,23 +124,21 @@ function testFormSubmission()
|
||||||
{
|
{
|
||||||
// Start the form submission test. As the form is submitted, the page is
|
// Start the form submission test. As the form is submitted, the page is
|
||||||
// loaded again. Bind to the load event to catch when this is done.
|
// loaded again. Bind to the load event to catch when this is done.
|
||||||
browser.addEventListener("load", function(aEvent) {
|
requestCallback = function() {
|
||||||
browser.removeEventListener(aEvent.type, arguments.callee, true);
|
|
||||||
|
|
||||||
ok(lastRequest, "testFormSubmission() was logged");
|
ok(lastRequest, "testFormSubmission() was logged");
|
||||||
is(lastRequest.method, "POST", "Method is correct");
|
is(lastRequest.request.method, "POST", "Method is correct");
|
||||||
isnot(lastRequest.request.body.
|
isnot(lastRequest.request.postData.text.
|
||||||
indexOf("Content-Type: application/x-www-form-urlencoded"), -1,
|
indexOf("Content-Type: application/x-www-form-urlencoded"), -1,
|
||||||
"Content-Type is correct");
|
"Content-Type is correct");
|
||||||
isnot(lastRequest.request.body.
|
isnot(lastRequest.request.postData.text.
|
||||||
indexOf("Content-Length: 20"), -1, "Content-length is correct");
|
indexOf("Content-Length: 20"), -1, "Content-length is correct");
|
||||||
isnot(lastRequest.request.body.
|
isnot(lastRequest.request.postData.text.
|
||||||
indexOf("name=foo+bar&age=144"), -1, "Form data is correct");
|
indexOf("name=foo+bar&age=144"), -1, "Form data is correct");
|
||||||
ok(lastRequest.response.body.indexOf("<!DOCTYPE HTML>") == 0,
|
is(lastRequest.response.content.text.indexOf("<!DOCTYPE HTML>"), 0,
|
||||||
"Response body's beginning is okay");
|
"Response body's beginning is okay");
|
||||||
|
|
||||||
executeSoon(testNetworkPanel);
|
executeSoon(testNetworkPanel);
|
||||||
}, true);
|
};
|
||||||
|
|
||||||
let form = content.document.querySelector("form");
|
let form = content.document.querySelector("form");
|
||||||
ok(form, "we have the HTML form");
|
ok(form, "we have the HTML form");
|
||||||
|
@ -152,19 +149,19 @@ function testNetworkPanel()
|
||||||
{
|
{
|
||||||
// Open the NetworkPanel. The functionality of the NetworkPanel is tested
|
// Open the NetworkPanel. The functionality of the NetworkPanel is tested
|
||||||
// within separate test files.
|
// within separate test files.
|
||||||
let networkPanel = HUDService.openNetworkPanel(hud.filterBox, lastRequest);
|
let networkPanel = HUDService.openNetworkPanel(hud.filterBox, lastActivity);
|
||||||
is(networkPanel, lastRequest.panels[0].get(),
|
is(networkPanel, hud.filterBox._netPanel,
|
||||||
"Network panel stored on lastRequest object");
|
"Network panel stored on anchor node");
|
||||||
|
|
||||||
networkPanel.panel.addEventListener("load", function(aEvent) {
|
networkPanel.panel.addEventListener("load", function onLoad(aEvent) {
|
||||||
networkPanel.panel.removeEventListener(aEvent.type, arguments.callee,
|
networkPanel.panel.removeEventListener(aEvent.type, onLoad, true);
|
||||||
true);
|
|
||||||
|
|
||||||
ok(true, "NetworkPanel was opened");
|
ok(true, "NetworkPanel was opened");
|
||||||
|
|
||||||
// All tests are done. Shutdown.
|
// All tests are done. Shutdown.
|
||||||
networkPanel.panel.hidePopup();
|
networkPanel.panel.hidePopup();
|
||||||
lastRequest = null;
|
lastRequest = null;
|
||||||
|
lastActivity = null;
|
||||||
HUDService.lastFinishedRequestCallback = null;
|
HUDService.lastFinishedRequestCallback = null;
|
||||||
executeSoon(finishTest);
|
executeSoon(finishTest);
|
||||||
}, true);
|
}, true);
|
||||||
|
|
|
@ -68,25 +68,39 @@ function testGen() {
|
||||||
let l10n = tempScope.WebConsoleUtils.l10n;
|
let l10n = tempScope.WebConsoleUtils.l10n;
|
||||||
tempScope = null;
|
tempScope = null;
|
||||||
|
|
||||||
var httpActivity = {
|
let httpActivity = {
|
||||||
|
meta: {
|
||||||
|
stages: [],
|
||||||
|
discardRequestBody: true,
|
||||||
|
discardResponseBody: true,
|
||||||
|
},
|
||||||
|
log: {
|
||||||
|
entries: [{
|
||||||
|
startedDateTime: (new Date()).toISOString(),
|
||||||
|
request: {
|
||||||
url: "http://www.testpage.com",
|
url: "http://www.testpage.com",
|
||||||
method: "GET",
|
method: "GET",
|
||||||
|
cookies: [],
|
||||||
panels: [],
|
headers: [
|
||||||
request: {
|
{ name: "foo", value: "bar" },
|
||||||
header: {
|
],
|
||||||
foo: "bar"
|
},
|
||||||
}
|
response: {
|
||||||
|
headers: [],
|
||||||
|
content: {},
|
||||||
|
},
|
||||||
|
timings: {},
|
||||||
|
}],
|
||||||
},
|
},
|
||||||
response: { },
|
|
||||||
timing: {
|
|
||||||
"REQUEST_HEADER": 0
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let entry = httpActivity.log.entries[0];
|
||||||
|
|
||||||
let networkPanel = HUDService.openNetworkPanel(filterBox, httpActivity);
|
let networkPanel = HUDService.openNetworkPanel(filterBox, httpActivity);
|
||||||
|
|
||||||
is (networkPanel, httpActivity.panels[0].get(), "Network panel stored on httpActivity object");
|
is(filterBox._netPanel, networkPanel,
|
||||||
|
"Network panel stored on the anchor object");
|
||||||
|
|
||||||
networkPanel.panel.addEventListener("load", function onLoad() {
|
networkPanel.panel.addEventListener("load", function onLoad() {
|
||||||
networkPanel.panel.removeEventListener("load", onLoad, true);
|
networkPanel.panel.removeEventListener("load", onLoad, true);
|
||||||
testDriver.next();
|
testDriver.next();
|
||||||
|
@ -94,6 +108,8 @@ function testGen() {
|
||||||
|
|
||||||
yield;
|
yield;
|
||||||
|
|
||||||
|
info("test 1");
|
||||||
|
|
||||||
checkIsVisible(networkPanel, {
|
checkIsVisible(networkPanel, {
|
||||||
requestCookie: false,
|
requestCookie: false,
|
||||||
requestFormData: false,
|
requestFormData: false,
|
||||||
|
@ -110,8 +126,11 @@ function testGen() {
|
||||||
checkNodeKeyValue(networkPanel, "requestHeadersContent", "foo", "bar");
|
checkNodeKeyValue(networkPanel, "requestHeadersContent", "foo", "bar");
|
||||||
|
|
||||||
// Test request body.
|
// Test request body.
|
||||||
httpActivity.request.body = "hello world";
|
info("test 2: request body");
|
||||||
|
httpActivity.meta.discardRequestBody = false;
|
||||||
|
entry.request.postData = { text: "hello world" };
|
||||||
networkPanel.update();
|
networkPanel.update();
|
||||||
|
|
||||||
checkIsVisible(networkPanel, {
|
checkIsVisible(networkPanel, {
|
||||||
requestBody: true,
|
requestBody: true,
|
||||||
requestFormData: false,
|
requestFormData: false,
|
||||||
|
@ -125,13 +144,19 @@ function testGen() {
|
||||||
checkNodeContent(networkPanel, "requestBodyContent", "hello world");
|
checkNodeContent(networkPanel, "requestBodyContent", "hello world");
|
||||||
|
|
||||||
// Test response header.
|
// Test response header.
|
||||||
httpActivity.timing.RESPONSE_HEADER = 1000;
|
info("test 3: response header");
|
||||||
httpActivity.response.status = "999 earthquake win";
|
entry.timings.wait = 10;
|
||||||
httpActivity.response.header = {
|
entry.response.httpVersion = "HTTP/3.14";
|
||||||
"Content-Type": "text/html",
|
entry.response.status = 999;
|
||||||
leaveHouses: "true"
|
entry.response.statusText = "earthquake win";
|
||||||
}
|
entry.response.content.mimeType = "text/html";
|
||||||
|
entry.response.headers.push(
|
||||||
|
{ name: "Content-Type", value: "text/html" },
|
||||||
|
{ name: "leaveHouses", value: "true" }
|
||||||
|
);
|
||||||
|
|
||||||
networkPanel.update();
|
networkPanel.update();
|
||||||
|
|
||||||
checkIsVisible(networkPanel, {
|
checkIsVisible(networkPanel, {
|
||||||
requestBody: true,
|
requestBody: true,
|
||||||
requestFormData: false,
|
requestFormData: false,
|
||||||
|
@ -143,13 +168,14 @@ function testGen() {
|
||||||
responseImageCached: false
|
responseImageCached: false
|
||||||
});
|
});
|
||||||
|
|
||||||
checkNodeContent(networkPanel, "header", "999 earthquake win");
|
checkNodeContent(networkPanel, "header", "HTTP/3.14 999 earthquake win");
|
||||||
checkNodeKeyValue(networkPanel, "responseHeadersContent", "leaveHouses", "true");
|
checkNodeKeyValue(networkPanel, "responseHeadersContent", "leaveHouses", "true");
|
||||||
checkNodeContent(networkPanel, "responseHeadersInfo", "1ms");
|
checkNodeContent(networkPanel, "responseHeadersInfo", "10ms");
|
||||||
|
|
||||||
httpActivity.timing.RESPONSE_COMPLETE = 2500;
|
info("test 4");
|
||||||
// This is necessary to show that the request is done.
|
|
||||||
httpActivity.timing.TRANSACTION_CLOSE = 2500;
|
httpActivity.meta.discardResponseBody = false;
|
||||||
|
entry.timings.receive = 2;
|
||||||
networkPanel.update();
|
networkPanel.update();
|
||||||
|
|
||||||
checkIsVisible(networkPanel, {
|
checkIsVisible(networkPanel, {
|
||||||
|
@ -163,7 +189,9 @@ function testGen() {
|
||||||
responseImageCached: false
|
responseImageCached: false
|
||||||
});
|
});
|
||||||
|
|
||||||
httpActivity.response.isDone = true;
|
info("test 5");
|
||||||
|
|
||||||
|
httpActivity.meta.stages.push("REQUEST_STOP", "TRANSACTION_CLOSE");
|
||||||
networkPanel.update();
|
networkPanel.update();
|
||||||
|
|
||||||
checkNodeContent(networkPanel, "responseNoBodyInfo", "2ms");
|
checkNodeContent(networkPanel, "responseNoBodyInfo", "2ms");
|
||||||
|
@ -180,11 +208,17 @@ function testGen() {
|
||||||
networkPanel.panel.hidePopup();
|
networkPanel.panel.hidePopup();
|
||||||
|
|
||||||
// Second run: Test for cookies and response body.
|
// Second run: Test for cookies and response body.
|
||||||
httpActivity.request.header.Cookie = "foo=bar; hello=world";
|
info("test 6: cookies and response body");
|
||||||
httpActivity.response.body = "get out here";
|
entry.request.cookies.push(
|
||||||
|
{ name: "foo", value: "bar" },
|
||||||
|
{ name: "hello", value: "world" }
|
||||||
|
);
|
||||||
|
entry.response.content.text = "get out here";
|
||||||
|
|
||||||
networkPanel = HUDService.openNetworkPanel(filterBox, httpActivity);
|
networkPanel = HUDService.openNetworkPanel(filterBox, httpActivity);
|
||||||
is (networkPanel, httpActivity.panels[1].get(), "Network panel stored on httpActivity object");
|
is(filterBox._netPanel, networkPanel,
|
||||||
|
"Network panel stored on httpActivity object");
|
||||||
|
|
||||||
networkPanel.panel.addEventListener("load", function onLoad() {
|
networkPanel.panel.addEventListener("load", function onLoad() {
|
||||||
networkPanel.panel.removeEventListener("load", onLoad, true);
|
networkPanel.panel.removeEventListener("load", onLoad, true);
|
||||||
testDriver.next();
|
testDriver.next();
|
||||||
|
@ -192,7 +226,6 @@ function testGen() {
|
||||||
|
|
||||||
yield;
|
yield;
|
||||||
|
|
||||||
|
|
||||||
checkIsVisible(networkPanel, {
|
checkIsVisible(networkPanel, {
|
||||||
requestBody: true,
|
requestBody: true,
|
||||||
requestFormData: false,
|
requestFormData: false,
|
||||||
|
@ -212,8 +245,10 @@ function testGen() {
|
||||||
networkPanel.panel.hidePopup();
|
networkPanel.panel.hidePopup();
|
||||||
|
|
||||||
// Check image request.
|
// Check image request.
|
||||||
httpActivity.response.header["Content-Type"] = "image/png";
|
info("test 7: image request");
|
||||||
httpActivity.url = TEST_IMG;
|
entry.response.headers[1].value = "image/png";
|
||||||
|
entry.response.content.mimeType = "image/png";
|
||||||
|
entry.request.url = TEST_IMG;
|
||||||
|
|
||||||
networkPanel = HUDService.openNetworkPanel(filterBox, httpActivity);
|
networkPanel = HUDService.openNetworkPanel(filterBox, httpActivity);
|
||||||
networkPanel.panel.addEventListener("load", function onLoad() {
|
networkPanel.panel.addEventListener("load", function onLoad() {
|
||||||
|
@ -259,7 +294,10 @@ function testGen() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check cached image request.
|
// Check cached image request.
|
||||||
httpActivity.response.status = "HTTP/1.1 304 Not Modified";
|
info("test 8: cached image request");
|
||||||
|
entry.response.httpVersion = "HTTP/1.1";
|
||||||
|
entry.response.status = 304;
|
||||||
|
entry.response.statusText = "Not Modified";
|
||||||
|
|
||||||
networkPanel = HUDService.openNetworkPanel(filterBox, httpActivity);
|
networkPanel = HUDService.openNetworkPanel(filterBox, httpActivity);
|
||||||
networkPanel.panel.addEventListener("load", function onLoad() {
|
networkPanel.panel.addEventListener("load", function onLoad() {
|
||||||
|
@ -286,11 +324,12 @@ function testGen() {
|
||||||
networkPanel.panel.hidePopup();
|
networkPanel.panel.hidePopup();
|
||||||
|
|
||||||
// Test sent form data.
|
// Test sent form data.
|
||||||
httpActivity.request.body = [
|
info("test 9: sent form data");
|
||||||
"Content-Type: application/x-www-form-urlencoded\n" +
|
entry.request.postData.text = [
|
||||||
"Content-Length: 59\n" +
|
"Content-Type: application/x-www-form-urlencoded",
|
||||||
|
"Content-Length: 59",
|
||||||
"name=rob&age=20"
|
"name=rob&age=20"
|
||||||
].join("");
|
].join("\n");
|
||||||
|
|
||||||
networkPanel = HUDService.openNetworkPanel(filterBox, httpActivity);
|
networkPanel = HUDService.openNetworkPanel(filterBox, httpActivity);
|
||||||
networkPanel.panel.addEventListener("load", function onLoad() {
|
networkPanel.panel.addEventListener("load", function onLoad() {
|
||||||
|
@ -316,7 +355,8 @@ function testGen() {
|
||||||
networkPanel.panel.hidePopup();
|
networkPanel.panel.hidePopup();
|
||||||
|
|
||||||
// Test no space after Content-Type:
|
// Test no space after Content-Type:
|
||||||
httpActivity.request.body = "Content-Type:application/x-www-form-urlencoded\n";
|
info("test 10: no space after Content-Type header in post data");
|
||||||
|
entry.request.postData.text = "Content-Type:application/x-www-form-urlencoded\n";
|
||||||
|
|
||||||
networkPanel = HUDService.openNetworkPanel(filterBox, httpActivity);
|
networkPanel = HUDService.openNetworkPanel(filterBox, httpActivity);
|
||||||
networkPanel.panel.addEventListener("load", function onLoad() {
|
networkPanel.panel.addEventListener("load", function onLoad() {
|
||||||
|
@ -341,25 +381,18 @@ function testGen() {
|
||||||
|
|
||||||
// Test cached data.
|
// Test cached data.
|
||||||
|
|
||||||
// Load a Latin-1 encoded page.
|
info("test 11: cached data");
|
||||||
browser.addEventListener("load", function onLoad () {
|
|
||||||
browser.removeEventListener("load", onLoad, true);
|
|
||||||
httpActivity.charset = content.document.characterSet;
|
|
||||||
testDriver.next();
|
|
||||||
}, true);
|
|
||||||
browser.contentWindow.wrappedJSObject.document.location = TEST_ENCODING_ISO_8859_1;
|
|
||||||
|
|
||||||
yield;
|
entry.request.url = TEST_ENCODING_ISO_8859_1;
|
||||||
|
entry.response.headers[1].value = "application/json";
|
||||||
httpActivity.url = TEST_ENCODING_ISO_8859_1;
|
entry.response.content.mimeType = "application/json";
|
||||||
httpActivity.response.header["Content-Type"] = "application/json";
|
entry.response.content.text = "my cached data is here!";
|
||||||
httpActivity.response.body = "";
|
|
||||||
|
|
||||||
networkPanel = HUDService.openNetworkPanel(filterBox, httpActivity);
|
networkPanel = HUDService.openNetworkPanel(filterBox, httpActivity);
|
||||||
networkPanel.isDoneCallback = function NP_doneCallback() {
|
networkPanel.panel.addEventListener("load", function onLoad() {
|
||||||
networkPanel.isDoneCallback = null;
|
networkPanel.panel.removeEventListener("load", onLoad, true);
|
||||||
testDriver.next();
|
testDriver.next();
|
||||||
}
|
}, true);
|
||||||
|
|
||||||
yield;
|
yield;
|
||||||
|
|
||||||
|
@ -375,21 +408,22 @@ function testGen() {
|
||||||
responseImageCached: false
|
responseImageCached: false
|
||||||
});
|
});
|
||||||
|
|
||||||
checkNodeContent(networkPanel, "responseBodyCachedContent", "<body>\u00fc\u00f6\u00E4</body>");
|
checkNodeContent(networkPanel, "responseBodyCachedContent",
|
||||||
|
"my cached data is here!");
|
||||||
|
|
||||||
networkPanel.panel.hidePopup();
|
networkPanel.panel.hidePopup();
|
||||||
|
|
||||||
// Test a response with a content type that can't be displayed in the
|
// Test a response with a content type that can't be displayed in the
|
||||||
// NetworkPanel.
|
// NetworkPanel.
|
||||||
httpActivity.response.header["Content-Type"] = "application/x-shockwave-flash";
|
info("test 12: unknown content type");
|
||||||
|
entry.response.headers[1].value = "application/x-shockwave-flash";
|
||||||
|
entry.response.content.mimeType = "application/x-shockwave-flash";
|
||||||
|
|
||||||
networkPanel = HUDService.openNetworkPanel(filterBox, httpActivity);
|
networkPanel = HUDService.openNetworkPanel(filterBox, httpActivity);
|
||||||
networkPanel.isDoneCallback = function NP_doneCallback() {
|
networkPanel.panel.addEventListener("load", function onLoad() {
|
||||||
networkPanel.isDoneCallback = null;
|
networkPanel.panel.removeEventListener("load", onLoad, true);
|
||||||
try {
|
|
||||||
testDriver.next();
|
testDriver.next();
|
||||||
} catch (e if e instanceof StopIteration) {
|
}, true);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
yield;
|
yield;
|
||||||
|
|
||||||
|
@ -453,4 +487,6 @@ function testGen() {
|
||||||
// All done!
|
// All done!
|
||||||
testDriver = null;
|
testDriver = null;
|
||||||
executeSoon(finishTest);
|
executeSoon(finishTest);
|
||||||
|
|
||||||
|
yield;
|
||||||
}
|
}
|
||||||
|
|
|
@ -306,6 +306,7 @@ addKeywordTitleAutoFill=Search %S
|
||||||
|
|
||||||
# TabView
|
# TabView
|
||||||
tabView2.title=%S - Group Your Tabs
|
tabView2.title=%S - Group Your Tabs
|
||||||
|
tabview2.moveToUnnamedGroup.label=%S and %S more
|
||||||
|
|
||||||
extensions.{972ce4c6-7e08-4474-a285-3208198ce6fd}.name=Default
|
extensions.{972ce4c6-7e08-4474-a285-3208198ce6fd}.name=Default
|
||||||
extensions.{972ce4c6-7e08-4474-a285-3208198ce6fd}.description=The default theme.
|
extensions.{972ce4c6-7e08-4474-a285-3208198ce6fd}.description=The default theme.
|
||||||
|
|
|
@ -42,22 +42,6 @@ pauseTooltip=Click to pause
|
||||||
# button when the debugger is in a paused state.
|
# button when the debugger is in a paused state.
|
||||||
resumeTooltip=Click to resume
|
resumeTooltip=Click to resume
|
||||||
|
|
||||||
# LOCALIZATION NOTE (localScope): The label that is displayed in the variables
|
|
||||||
# pane as a header on the local scope container.
|
|
||||||
localScope=Local
|
|
||||||
|
|
||||||
# LOCALIZATION NOTE (globalScope): The label that is displayed in the variables
|
|
||||||
# pane as a header on the globel scope container.
|
|
||||||
globalScope=Global
|
|
||||||
|
|
||||||
# LOCALIZATION NOTE (withScope): The label that is displayed in the variables
|
|
||||||
# pane as a header on the container for identifiers in a with block.
|
|
||||||
withScope=With block
|
|
||||||
|
|
||||||
# LOCALIZATION NOTE (closureScope): The label that is displayed in the variables
|
|
||||||
# pane as a header on container for identifiers in a closure scope.
|
|
||||||
closureScope=Closure
|
|
||||||
|
|
||||||
# LOCALIZATION NOTE (emptyStackText): The text that is displayed in the stack
|
# LOCALIZATION NOTE (emptyStackText): The text that is displayed in the stack
|
||||||
# frames list when there are no frames to display.
|
# frames list when there are no frames to display.
|
||||||
emptyStackText=No stacks to display.
|
emptyStackText=No stacks to display.
|
||||||
|
@ -72,3 +56,17 @@ loadingText=Loading\u2026
|
||||||
# external resource file.
|
# external resource file.
|
||||||
# %1$S=URL, %2$S=status code
|
# %1$S=URL, %2$S=status code
|
||||||
loadingError=Error loading %1$S: %2$S
|
loadingError=Error loading %1$S: %2$S
|
||||||
|
|
||||||
|
# LOCALIZATION NOTE (emptyVariablesText): The text that is displayed in the
|
||||||
|
# variables pane when there are no variables to display.
|
||||||
|
emptyVariablesText=No variables to display.
|
||||||
|
|
||||||
|
# LOCALIZATION NOTE (scopeLabel): The text that is displayed in the variables
|
||||||
|
# pane as a header for each variable scope (e.g. "Global scope, "With scope",
|
||||||
|
# etc.).
|
||||||
|
scopeLabel=%S scope
|
||||||
|
|
||||||
|
# LOCALIZATION NOTE (globalScopeLabel): The name of the global scope. This text
|
||||||
|
# is added to scopeLabel and displayed in the variables pane as a header for
|
||||||
|
# the global scope.
|
||||||
|
globalScopeLabel=Global
|
||||||
|
|
|
@ -178,6 +178,28 @@ prefListSearchDesc=Filter the list of settings displayed
|
||||||
# for help on what it does.
|
# for help on what it does.
|
||||||
prefListSearchManual=Search for the given string in the list of available preferences
|
prefListSearchManual=Search for the given string in the list of available preferences
|
||||||
|
|
||||||
|
# LOCALIZATION NOTE (prefShowDesc): A very short description of the 'pref
|
||||||
|
# show' 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. See
|
||||||
|
# prefShowManual for a fuller description of what it does.
|
||||||
|
prefShowDesc=Display setting value
|
||||||
|
|
||||||
|
# LOCALIZATION NOTE (prefShowManual): A fuller description of the 'pref show'
|
||||||
|
# command. Displayed when the user asks for help on what it does.
|
||||||
|
prefShowManual=Display the value of a given preference
|
||||||
|
|
||||||
|
# LOCALIZATION NOTE (prefShowSettingDesc): A short description of the
|
||||||
|
# 'setting' parameter to the 'pref show' command. See prefShowSettingManual
|
||||||
|
# for a fuller description of what it does. This string is designed to be
|
||||||
|
# shown in a dialog with restricted space, which is why it should be as short
|
||||||
|
# as possible.
|
||||||
|
prefShowSettingDesc=Setting to display
|
||||||
|
|
||||||
|
# LOCALIZATION NOTE (prefShowSettingManual): A fuller description of the
|
||||||
|
# 'setting' parameter to the 'pref show' command. Displayed when the user asks
|
||||||
|
# for help on what it does.
|
||||||
|
prefShowSettingManual=The name of the setting to display
|
||||||
|
|
||||||
# LOCALIZATION NOTE (prefSetDesc): A very short description of the 'pref set'
|
# LOCALIZATION NOTE (prefSetDesc): A very short description of the 'pref set'
|
||||||
# command. This string is designed to be shown in a menu alongside the command
|
# 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. See prefSetManual for
|
# name, which is why it should be as short as possible. See prefSetManual for
|
||||||
|
@ -272,6 +294,31 @@ introDesc=Show the opening message
|
||||||
# command. Displayed when the user asks for help on what it does.
|
# command. Displayed when the user asks for help on what it does.
|
||||||
introManual=Redisplay the message that is shown to new users until they click the 'Got it!' button
|
introManual=Redisplay the message that is shown to new users until they click the 'Got it!' button
|
||||||
|
|
||||||
|
# LOCALIZATION NOTE (introTextOpening): The 'intro text' opens when the user
|
||||||
|
# first opens the developer toolbar to explain the command line, and is shown
|
||||||
|
# each time it is opened until the user clicks the 'Got it!' button. This
|
||||||
|
# string is the opening paragraph of the intro text.
|
||||||
|
introTextOpening=The Firefox command line is designed for developers. It focuses on speed of input over JavaScript syntax and a rich display over monospace output.
|
||||||
|
|
||||||
|
# LOCALIZATION NOTE (introTextCommands): For information about the 'intro
|
||||||
|
# text' see introTextOpening. The second paragraph is in 2 sections, the first
|
||||||
|
# section points the user to the 'help' command.
|
||||||
|
introTextCommands=For a list of commands type
|
||||||
|
|
||||||
|
# LOCALIZATION NOTE (introTextKeys): For information about the 'intro text'
|
||||||
|
# see introTextOpening. The second section in the second paragraph points the
|
||||||
|
# user to the F1/Escape keys which show and hide hints.
|
||||||
|
introTextKeys=or to show/hide command hints press
|
||||||
|
|
||||||
|
# LOCALIZATION NOTE (introTextF1Escape): For information about the 'intro
|
||||||
|
# text' see introTextOpening. This string is used with introTextKeys, and
|
||||||
|
# contains the keys that are pressed to open and close hints.
|
||||||
|
introTextF1Escape=F1/Escape
|
||||||
|
|
||||||
|
# LOCALIZATION NOTE (introTextGo): For information about the 'intro text' see
|
||||||
|
# introTextOpening. The text on the button that dismisses the intro text.
|
||||||
|
introTextGo=Got it!
|
||||||
|
|
||||||
# LOCALIZATION NOTE (hideIntroDesc): Short description of the 'hideIntro'
|
# LOCALIZATION NOTE (hideIntroDesc): Short description of the 'hideIntro'
|
||||||
# setting. Displayed when the user asks for help on the settings.
|
# setting. Displayed when the user asks for help on the settings.
|
||||||
hideIntroDesc=Show the initial welcome message
|
hideIntroDesc=Show the initial welcome message
|
||||||
|
|
|
@ -195,7 +195,7 @@
|
||||||
* Animations
|
* Animations
|
||||||
*/
|
*/
|
||||||
|
|
||||||
.details[open] {
|
.details[open][animated] {
|
||||||
-moz-animation-duration: 0.25s;
|
-moz-animation-duration: 0.25s;
|
||||||
-moz-animation-name: showblock;
|
-moz-animation-name: showblock;
|
||||||
}
|
}
|
||||||
|
|
|
@ -194,7 +194,7 @@
|
||||||
* Animations
|
* Animations
|
||||||
*/
|
*/
|
||||||
|
|
||||||
.details[open] {
|
.details[open][animated] {
|
||||||
-moz-animation-duration: 0.25s;
|
-moz-animation-duration: 0.25s;
|
||||||
-moz-animation-name: showblock;
|
-moz-animation-name: showblock;
|
||||||
}
|
}
|
||||||
|
|
|
@ -198,7 +198,7 @@
|
||||||
* Animations
|
* Animations
|
||||||
*/
|
*/
|
||||||
|
|
||||||
.details[open] {
|
.details[open][animated] {
|
||||||
-moz-animation-duration: 0.25s;
|
-moz-animation-duration: 0.25s;
|
||||||
-moz-animation-name: showblock;
|
-moz-animation-name: showblock;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1078,6 +1078,10 @@ ObjectActor.prototype = {
|
||||||
message: "cannot access the environment of this function." };
|
message: "cannot access the environment of this function." };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// XXX: the following call of env.form() won't work until bug 747514 lands.
|
||||||
|
// We can't get to the frame that defined this function's environment,
|
||||||
|
// neither here, nor during ObjectActor's construction. Luckily, we don't
|
||||||
|
// use the 'scope' request in the debugger frontend.
|
||||||
return { name: this.obj.name || null,
|
return { name: this.obj.name || null,
|
||||||
scope: envActor.form(this.obj) };
|
scope: envActor.form(this.obj) };
|
||||||
},
|
},
|
||||||
|
@ -1197,14 +1201,7 @@ FrameActor.prototype = {
|
||||||
type: this.frame.type };
|
type: this.frame.type };
|
||||||
if (this.frame.type === "call") {
|
if (this.frame.type === "call") {
|
||||||
form.callee = this.threadActor.createValueGrip(this.frame.callee);
|
form.callee = this.threadActor.createValueGrip(this.frame.callee);
|
||||||
if (this.frame.callee.name) {
|
form.calleeName = getFunctionName(this.frame.callee);
|
||||||
form.calleeName = this.frame.callee.name;
|
|
||||||
} else {
|
|
||||||
let desc = this.frame.callee.getOwnPropertyDescriptor("displayName");
|
|
||||||
if (desc && desc.value && typeof desc.value == "string") {
|
|
||||||
form.calleeName = desc.value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let envActor = this.threadActor
|
let envActor = this.threadActor
|
||||||
|
@ -1335,13 +1332,13 @@ EnvironmentActor.prototype = {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns an environment form for use in a protocol message. Note that the
|
* Returns an environment form for use in a protocol message. Note that the
|
||||||
* requirement of passing the frame or function as a parameter is only
|
* requirement of passing the frame as a parameter is only temporary, since
|
||||||
* temporary, since when bug 747514 lands, the environment will have a callee
|
* when bug 747514 lands, the environment will have a callee property that
|
||||||
* property that will contain it.
|
* will contain it.
|
||||||
*
|
*
|
||||||
* @param object aObject
|
* @param Debugger.Frame aObject
|
||||||
* The stack frame or function object whose environment bindings are
|
* The stack frame object whose environment bindings are being
|
||||||
* being generated.
|
* generated.
|
||||||
*/
|
*/
|
||||||
form: function EA_form(aObject) {
|
form: function EA_form(aObject) {
|
||||||
// Debugger.Frame might be dead by the time we get here, which will cause
|
// Debugger.Frame might be dead by the time we get here, which will cause
|
||||||
|
@ -1353,24 +1350,29 @@ EnvironmentActor.prototype = {
|
||||||
let parent;
|
let parent;
|
||||||
if (this.obj.parent) {
|
if (this.obj.parent) {
|
||||||
let thread = this.threadActor;
|
let thread = this.threadActor;
|
||||||
parent = thread.createEnvironmentActor(this.obj.parent.environment,
|
parent = thread.createEnvironmentActor(this.obj.parent,
|
||||||
this.registeredPool);
|
this.registeredPool);
|
||||||
}
|
}
|
||||||
let form = { actor: this.actorID,
|
// Deduce the frame that created the parent scope in order to pass it to
|
||||||
parent: parent ? parent.form(this.obj.parent) : parent };
|
// parent.form(). TODO: this can be removed after bug 747514 is done.
|
||||||
|
let parentFrame = aObject;
|
||||||
if (aObject.type == "object") {
|
if (this.obj.type == "declarative" && aObject.older) {
|
||||||
if (this.obj.parent) {
|
parentFrame = aObject.older;
|
||||||
form.type = "with";
|
|
||||||
} else {
|
|
||||||
form.type = "object";
|
|
||||||
}
|
}
|
||||||
form.object = this.threadActor.createValueGrip(aObject.object);
|
let form = { actor: this.actorID,
|
||||||
} else {
|
parent: parent ? parent.form(parentFrame) : parent };
|
||||||
if (aObject.class == "Function") {
|
|
||||||
|
if (this.obj.type == "with") {
|
||||||
|
form.type = "with";
|
||||||
|
form.object = this.threadActor.createValueGrip(this.obj.object);
|
||||||
|
} else if (this.obj.type == "object") {
|
||||||
|
form.type = "object";
|
||||||
|
form.object = this.threadActor.createValueGrip(this.obj.object);
|
||||||
|
} else { // this.obj.type == "declarative"
|
||||||
|
if (aObject.callee) {
|
||||||
form.type = "function";
|
form.type = "function";
|
||||||
form.function = this.threadActor.createValueGrip(aObject);
|
form.function = this.threadActor.createValueGrip(aObject.callee);
|
||||||
form.functionName = aObject.name;
|
form.functionName = getFunctionName(aObject.callee);
|
||||||
} else {
|
} else {
|
||||||
form.type = "block";
|
form.type = "block";
|
||||||
}
|
}
|
||||||
|
@ -1382,14 +1384,14 @@ EnvironmentActor.prototype = {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the identifier bindings object as required by the remote protocol
|
* Return the identifier bindings object as required by the remote protocol
|
||||||
* specification. Note that the requirement of passing the frame or function
|
* specification. Note that the requirement of passing the frame as a
|
||||||
* as a parameter is only temporary, since when bug 747514 lands, the
|
* parameter is only temporary, since when bug 747514 lands, the environment
|
||||||
* environment will have a callee property that will contain it.
|
* will have a callee property that will contain it.
|
||||||
*
|
*
|
||||||
* @param object aObject [optional]
|
* @param Debugger.Frame aObject [optional]
|
||||||
* The stack frame or function object whose environment bindings are
|
* The stack frame whose environment bindings are being generated. When
|
||||||
* being generated. When left unspecified, the bindings do not contain
|
* left unspecified, the bindings do not contain an 'arguments'
|
||||||
* an 'arguments' property.
|
* property.
|
||||||
*/
|
*/
|
||||||
_bindings: function EA_bindings(aObject) {
|
_bindings: function EA_bindings(aObject) {
|
||||||
let bindings = { arguments: [], variables: {} };
|
let bindings = { arguments: [], variables: {} };
|
||||||
|
@ -1514,3 +1516,22 @@ EnvironmentActor.prototype.requestTypes = {
|
||||||
"assign": EnvironmentActor.prototype.onAssign,
|
"assign": EnvironmentActor.prototype.onAssign,
|
||||||
"bindings": EnvironmentActor.prototype.onBindings
|
"bindings": EnvironmentActor.prototype.onBindings
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper function to deduce the name of the provided function.
|
||||||
|
*
|
||||||
|
* @param Debugger.Object aFunction
|
||||||
|
* The function whose name will be returned.
|
||||||
|
*/
|
||||||
|
function getFunctionName(aFunction) {
|
||||||
|
let name;
|
||||||
|
if (aFunction.name) {
|
||||||
|
name = aFunction.name;
|
||||||
|
} else {
|
||||||
|
let desc = aFunction.getOwnPropertyDescriptor("displayName");
|
||||||
|
if (desc && desc.value && typeof desc.value == "string") {
|
||||||
|
name = desc.value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,62 @@
|
||||||
|
/* Any copyright is dedicated to the Public Domain.
|
||||||
|
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check a frame actor's parent bindings.
|
||||||
|
*/
|
||||||
|
|
||||||
|
var gDebuggee;
|
||||||
|
var gClient;
|
||||||
|
var gThreadClient;
|
||||||
|
|
||||||
|
function run_test()
|
||||||
|
{
|
||||||
|
initTestDebuggerServer();
|
||||||
|
gDebuggee = addTestGlobal("test-stack");
|
||||||
|
gClient = new DebuggerClient(DebuggerServer.connectPipe());
|
||||||
|
gClient.connect(function() {
|
||||||
|
attachTestGlobalClientAndResume(gClient, "test-stack", function(aResponse, aThreadClient) {
|
||||||
|
gThreadClient = aThreadClient;
|
||||||
|
test_pause_frame();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
do_test_pending();
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_pause_frame()
|
||||||
|
{
|
||||||
|
gThreadClient.addOneTimeListener("paused", function(aEvent, aPacket) {
|
||||||
|
let parentEnv = aPacket.frame.environment.parent;
|
||||||
|
let bindings = parentEnv.bindings;
|
||||||
|
let args = bindings.arguments;
|
||||||
|
let vars = bindings.variables;
|
||||||
|
do_check_neq(parentEnv, undefined);
|
||||||
|
do_check_eq(args.length, 0);
|
||||||
|
do_check_eq(vars.stopMe.value.type, "object");
|
||||||
|
do_check_eq(vars.stopMe.value.class, "Function");
|
||||||
|
do_check_true(!!vars.stopMe.value.actor);
|
||||||
|
|
||||||
|
parentEnv = parentEnv.parent;
|
||||||
|
do_check_neq(parentEnv, undefined);
|
||||||
|
let objClient = gThreadClient.pauseGrip(parentEnv.object);
|
||||||
|
objClient.getPrototypeAndProperties(function(aResponse) {
|
||||||
|
do_check_eq(aResponse.ownProperties.Object.value.type, "object");
|
||||||
|
do_check_eq(aResponse.ownProperties.Object.value.class, "Function");
|
||||||
|
do_check_true(!!aResponse.ownProperties.Object.value.actor);
|
||||||
|
|
||||||
|
gThreadClient.resume(function() {
|
||||||
|
finishClient(gClient);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
gDebuggee.eval("(" + function() {
|
||||||
|
function stopMe(aNumber, aBool, aString, aNull, aUndefined, aObject) {
|
||||||
|
var a = 1;
|
||||||
|
var b = true;
|
||||||
|
var c = { a: "a" };
|
||||||
|
debugger;
|
||||||
|
};
|
||||||
|
stopMe(42, true, "nasu", null, undefined, { foo: "bar" });
|
||||||
|
} + ")()");
|
||||||
|
}
|
|
@ -0,0 +1,69 @@
|
||||||
|
/* Any copyright is dedicated to the Public Domain.
|
||||||
|
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check a |with| frame actor's bindings.
|
||||||
|
*/
|
||||||
|
|
||||||
|
var gDebuggee;
|
||||||
|
var gClient;
|
||||||
|
var gThreadClient;
|
||||||
|
|
||||||
|
function run_test()
|
||||||
|
{
|
||||||
|
initTestDebuggerServer();
|
||||||
|
gDebuggee = addTestGlobal("test-stack");
|
||||||
|
gClient = new DebuggerClient(DebuggerServer.connectPipe());
|
||||||
|
gClient.connect(function() {
|
||||||
|
attachTestGlobalClientAndResume(gClient, "test-stack", function(aResponse, aThreadClient) {
|
||||||
|
gThreadClient = aThreadClient;
|
||||||
|
test_pause_frame();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
do_test_pending();
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_pause_frame()
|
||||||
|
{
|
||||||
|
gThreadClient.addOneTimeListener("paused", function(aEvent, aPacket) {
|
||||||
|
let env = aPacket.frame.environment;
|
||||||
|
do_check_neq(env, undefined);
|
||||||
|
|
||||||
|
let parentEnv = env.parent;
|
||||||
|
do_check_neq(parentEnv, undefined);
|
||||||
|
|
||||||
|
let bindings = parentEnv.bindings;
|
||||||
|
let args = bindings.arguments;
|
||||||
|
let vars = bindings.variables;
|
||||||
|
do_check_eq(args.length, 1);
|
||||||
|
do_check_eq(args[0].aNumber.value, 10);
|
||||||
|
do_check_eq(vars.r.value, 10);
|
||||||
|
do_check_eq(vars.a.value, Math.PI * 100);
|
||||||
|
do_check_eq(vars.arguments.value.class, "Arguments");
|
||||||
|
do_check_true(!!vars.arguments.value.actor);
|
||||||
|
|
||||||
|
let objClient = gThreadClient.pauseGrip(env.object);
|
||||||
|
objClient.getPrototypeAndProperties(function(aResponse) {
|
||||||
|
do_check_eq(aResponse.ownProperties.PI.value, Math.PI);
|
||||||
|
do_check_eq(aResponse.ownProperties.cos.value.type, "object");
|
||||||
|
do_check_eq(aResponse.ownProperties.cos.value.class, "Function");
|
||||||
|
do_check_true(!!aResponse.ownProperties.cos.value.actor);
|
||||||
|
|
||||||
|
gThreadClient.resume(function() {
|
||||||
|
finishClient(gClient);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
gDebuggee.eval("(" + function() {
|
||||||
|
function stopMe(aNumber) {
|
||||||
|
var a;
|
||||||
|
var r = aNumber;
|
||||||
|
with (Math) {
|
||||||
|
a = PI * r * r;
|
||||||
|
debugger;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
stopMe(10);
|
||||||
|
} + ")()");
|
||||||
|
}
|
|
@ -0,0 +1,84 @@
|
||||||
|
/* Any copyright is dedicated to the Public Domain.
|
||||||
|
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check the environment bindongs of a |with| within a |with|.
|
||||||
|
*/
|
||||||
|
|
||||||
|
var gDebuggee;
|
||||||
|
var gClient;
|
||||||
|
var gThreadClient;
|
||||||
|
|
||||||
|
function run_test()
|
||||||
|
{
|
||||||
|
initTestDebuggerServer();
|
||||||
|
gDebuggee = addTestGlobal("test-stack");
|
||||||
|
gClient = new DebuggerClient(DebuggerServer.connectPipe());
|
||||||
|
gClient.connect(function() {
|
||||||
|
attachTestGlobalClientAndResume(gClient, "test-stack", function(aResponse, aThreadClient) {
|
||||||
|
gThreadClient = aThreadClient;
|
||||||
|
test_pause_frame();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
do_test_pending();
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_pause_frame()
|
||||||
|
{
|
||||||
|
gThreadClient.addOneTimeListener("paused", function(aEvent, aPacket) {
|
||||||
|
let env = aPacket.frame.environment;
|
||||||
|
do_check_neq(env, undefined);
|
||||||
|
|
||||||
|
let objClient = gThreadClient.pauseGrip(env.object);
|
||||||
|
objClient.getPrototypeAndProperties(function(aResponse) {
|
||||||
|
do_check_eq(aResponse.ownProperties.one.value, 1);
|
||||||
|
do_check_eq(aResponse.ownProperties.two.value, 2);
|
||||||
|
do_check_eq(aResponse.ownProperties.foo, undefined);
|
||||||
|
|
||||||
|
let parentEnv = env.parent;
|
||||||
|
do_check_neq(parentEnv, undefined);
|
||||||
|
|
||||||
|
let parentClient = gThreadClient.pauseGrip(parentEnv.object);
|
||||||
|
parentClient.getPrototypeAndProperties(function(aResponse) {
|
||||||
|
do_check_eq(aResponse.ownProperties.PI.value, Math.PI);
|
||||||
|
do_check_eq(aResponse.ownProperties.cos.value.type, "object");
|
||||||
|
do_check_eq(aResponse.ownProperties.cos.value.class, "Function");
|
||||||
|
do_check_true(!!aResponse.ownProperties.cos.value.actor);
|
||||||
|
|
||||||
|
parentEnv = parentEnv.parent;
|
||||||
|
do_check_neq(parentEnv, undefined);
|
||||||
|
|
||||||
|
let bindings = parentEnv.bindings;
|
||||||
|
let args = bindings.arguments;
|
||||||
|
let vars = bindings.variables;
|
||||||
|
do_check_eq(args.length, 1);
|
||||||
|
do_check_eq(args[0].aNumber.value, 10);
|
||||||
|
do_check_eq(vars.r.value, 10);
|
||||||
|
do_check_eq(vars.a.value, Math.PI * 100);
|
||||||
|
do_check_eq(vars.arguments.value.class, "Arguments");
|
||||||
|
do_check_true(!!vars.arguments.value.actor);
|
||||||
|
do_check_eq(vars.foo.value, 2 * Math.PI);
|
||||||
|
|
||||||
|
gThreadClient.resume(function() {
|
||||||
|
finishClient(gClient);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
gDebuggee.eval("(" + function() {
|
||||||
|
function stopMe(aNumber) {
|
||||||
|
var a, obj = { one: 1, two: 2 };
|
||||||
|
var r = aNumber;
|
||||||
|
with (Math) {
|
||||||
|
a = PI * r * r;
|
||||||
|
with (obj) {
|
||||||
|
var foo = two * PI;
|
||||||
|
debugger;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
stopMe(10);
|
||||||
|
} + ")()");
|
||||||
|
}
|
|
@ -0,0 +1,62 @@
|
||||||
|
/* Any copyright is dedicated to the Public Domain.
|
||||||
|
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check the environment bindings of a |with| in global scope.
|
||||||
|
*/
|
||||||
|
|
||||||
|
var gDebuggee;
|
||||||
|
var gClient;
|
||||||
|
var gThreadClient;
|
||||||
|
|
||||||
|
function run_test()
|
||||||
|
{
|
||||||
|
initTestDebuggerServer();
|
||||||
|
gDebuggee = addTestGlobal("test-stack");
|
||||||
|
gClient = new DebuggerClient(DebuggerServer.connectPipe());
|
||||||
|
gClient.connect(function() {
|
||||||
|
attachTestGlobalClientAndResume(gClient, "test-stack", function(aResponse, aThreadClient) {
|
||||||
|
gThreadClient = aThreadClient;
|
||||||
|
test_pause_frame();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
do_test_pending();
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_pause_frame()
|
||||||
|
{
|
||||||
|
gThreadClient.addOneTimeListener("paused", function(aEvent, aPacket) {
|
||||||
|
let env = aPacket.frame.environment;
|
||||||
|
do_check_neq(env, undefined);
|
||||||
|
|
||||||
|
let objClient = gThreadClient.pauseGrip(env.object);
|
||||||
|
objClient.getPrototypeAndProperties(function(aResponse) {
|
||||||
|
do_check_eq(aResponse.ownProperties.PI.value, Math.PI);
|
||||||
|
do_check_eq(aResponse.ownProperties.cos.value.type, "object");
|
||||||
|
do_check_eq(aResponse.ownProperties.cos.value.class, "Function");
|
||||||
|
do_check_true(!!aResponse.ownProperties.cos.value.actor);
|
||||||
|
|
||||||
|
let parentEnv = env.parent;
|
||||||
|
do_check_neq(parentEnv, undefined);
|
||||||
|
|
||||||
|
let parentClient = gThreadClient.pauseGrip(parentEnv.object);
|
||||||
|
parentClient.getPrototypeAndProperties(function(aResponse) {
|
||||||
|
do_check_eq(aResponse.ownProperties.a.value, Math.PI * 100);
|
||||||
|
do_check_eq(aResponse.ownProperties.r.value, 10);
|
||||||
|
do_check_eq(aResponse.ownProperties.Object.value.type, "object");
|
||||||
|
do_check_eq(aResponse.ownProperties.Object.value.class, "Function");
|
||||||
|
do_check_true(!!aResponse.ownProperties.Object.value.actor);
|
||||||
|
|
||||||
|
gThreadClient.resume(function() {
|
||||||
|
finishClient(gClient);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
gDebuggee.eval("var a, r = 10;\n" +
|
||||||
|
"with (Math) {\n" +
|
||||||
|
" a = PI * r * r;\n" +
|
||||||
|
" debugger;\n" +
|
||||||
|
"}");
|
||||||
|
}
|
|
@ -54,3 +54,7 @@ tail =
|
||||||
[test_stepping-03.js]
|
[test_stepping-03.js]
|
||||||
[test_stepping-04.js]
|
[test_stepping-04.js]
|
||||||
[test_framebindings-01.js]
|
[test_framebindings-01.js]
|
||||||
|
[test_framebindings-02.js]
|
||||||
|
[test_framebindings-03.js]
|
||||||
|
[test_framebindings-04.js]
|
||||||
|
[test_framebindings-05.js]
|
||||||
|
|
|
@ -322,7 +322,7 @@ AddonCompatibilityOverride.prototype = {
|
||||||
* A type of add-on, used by the UI to determine how to display different types
|
* A type of add-on, used by the UI to determine how to display different types
|
||||||
* of add-ons.
|
* of add-ons.
|
||||||
*
|
*
|
||||||
* @param aId
|
* @param aID
|
||||||
* The add-on type ID
|
* The add-on type ID
|
||||||
* @param aLocaleURI
|
* @param aLocaleURI
|
||||||
* The URI of a localized properties file to get the displayable name
|
* The URI of a localized properties file to get the displayable name
|
||||||
|
@ -340,15 +340,15 @@ AddonCompatibilityOverride.prototype = {
|
||||||
* An option set of flags that customize the display of the add-on in
|
* An option set of flags that customize the display of the add-on in
|
||||||
* the UI.
|
* the UI.
|
||||||
*/
|
*/
|
||||||
function AddonType(aId, aLocaleURI, aLocaleKey, aViewType, aUIPriority, aFlags) {
|
function AddonType(aID, aLocaleURI, aLocaleKey, aViewType, aUIPriority, aFlags) {
|
||||||
if (!aId)
|
if (!aID)
|
||||||
throw new Error("An AddonType must have an ID");
|
throw new Error("An AddonType must have an ID");
|
||||||
if (aViewType && aUIPriority === undefined)
|
if (aViewType && aUIPriority === undefined)
|
||||||
throw new Error("An AddonType with a defined view must have a set UI priority");
|
throw new Error("An AddonType with a defined view must have a set UI priority");
|
||||||
if (!aLocaleKey)
|
if (!aLocaleKey)
|
||||||
throw new Error("An AddonType must have a displayable name");
|
throw new Error("An AddonType must have a displayable name");
|
||||||
|
|
||||||
this.id = aId;
|
this.id = aID;
|
||||||
this.uiPriority = aUIPriority;
|
this.uiPriority = aUIPriority;
|
||||||
this.viewType = aViewType;
|
this.viewType = aViewType;
|
||||||
this.flags = aFlags;
|
this.flags = aFlags;
|
||||||
|
@ -357,7 +357,7 @@ function AddonType(aId, aLocaleURI, aLocaleKey, aViewType, aUIPriority, aFlags)
|
||||||
this.__defineGetter__("name", function() {
|
this.__defineGetter__("name", function() {
|
||||||
delete this.name;
|
delete this.name;
|
||||||
let bundle = Services.strings.createBundle(aLocaleURI);
|
let bundle = Services.strings.createBundle(aLocaleURI);
|
||||||
this.name = bundle.GetStringFromName(aLocaleKey.replace("%ID%", aId));
|
this.name = bundle.GetStringFromName(aLocaleKey.replace("%ID%", aID));
|
||||||
return this.name;
|
return this.name;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -555,9 +555,17 @@ var AddonManagerInternal = {
|
||||||
* @param aProvider
|
* @param aProvider
|
||||||
* The provider to register
|
* The provider to register
|
||||||
* @param aTypes
|
* @param aTypes
|
||||||
* An array of add-on types
|
* An optional array of add-on types
|
||||||
*/
|
*/
|
||||||
registerProvider: function AMI_registerProvider(aProvider, aTypes) {
|
registerProvider: function AMI_registerProvider(aProvider, aTypes) {
|
||||||
|
if (!aProvider || typeof aProvider != "object")
|
||||||
|
throw Components.Exception("aProvider must be specified",
|
||||||
|
Cr.NS_ERROR_INVALID_ARG);
|
||||||
|
|
||||||
|
if (aTypes && !Array.isArray(aTypes))
|
||||||
|
throw Components.Exception("aTypes must be an array or null",
|
||||||
|
Cr.NS_ERROR_INVALID_ARG);
|
||||||
|
|
||||||
this.providers.push(aProvider);
|
this.providers.push(aProvider);
|
||||||
|
|
||||||
if (aTypes) {
|
if (aTypes) {
|
||||||
|
@ -597,6 +605,10 @@ var AddonManagerInternal = {
|
||||||
* The provider to unregister
|
* The provider to unregister
|
||||||
*/
|
*/
|
||||||
unregisterProvider: function AMI_unregisterProvider(aProvider) {
|
unregisterProvider: function AMI_unregisterProvider(aProvider) {
|
||||||
|
if (!aProvider || typeof aProvider != "object")
|
||||||
|
throw Components.Exception("aProvider must be specified",
|
||||||
|
Cr.NS_ERROR_INVALID_ARG);
|
||||||
|
|
||||||
let pos = 0;
|
let pos = 0;
|
||||||
while (pos < this.providers.length) {
|
while (pos < this.providers.length) {
|
||||||
if (this.providers[pos] == aProvider)
|
if (this.providers[pos] == aProvider)
|
||||||
|
@ -739,15 +751,27 @@ var AddonManagerInternal = {
|
||||||
* appropriate values.
|
* appropriate values.
|
||||||
*
|
*
|
||||||
* @param aAddon
|
* @param aAddon
|
||||||
* The AddonInternal representing the add-on
|
* The Addon representing the add-on
|
||||||
* @param aUri
|
* @param aUri
|
||||||
* The uri to escape
|
* The string representation of the URI to escape
|
||||||
* @param aAppVersion
|
* @param aAppVersion
|
||||||
* The optional application version to use for %APP_VERSION%
|
* The optional application version to use for %APP_VERSION%
|
||||||
* @return the appropriately escaped uri.
|
* @return The appropriately escaped URI.
|
||||||
*/
|
*/
|
||||||
escapeAddonURI: function AMI_escapeAddonURI(aAddon, aUri, aAppVersion)
|
escapeAddonURI: function AMI_escapeAddonURI(aAddon, aUri, aAppVersion)
|
||||||
{
|
{
|
||||||
|
if (!aAddon || typeof aAddon != "object")
|
||||||
|
throw Components.Exception("aAddon must be an Addon object",
|
||||||
|
Cr.NS_ERROR_INVALID_ARG);
|
||||||
|
|
||||||
|
if (!aUri || typeof aUri != "string")
|
||||||
|
throw Components.Exception("aUri must be a non-empty string",
|
||||||
|
Cr.NS_ERROR_INVALID_ARG);
|
||||||
|
|
||||||
|
if (aAppVersion && typeof aAppVersion != "string")
|
||||||
|
throw Components.Exception("aAppVersion must be a string or null",
|
||||||
|
Cr.NS_ERROR_INVALID_ARG);
|
||||||
|
|
||||||
var addonStatus = aAddon.userDisabled || aAddon.softDisabled ? "userDisabled"
|
var addonStatus = aAddon.userDisabled || aAddon.softDisabled ? "userDisabled"
|
||||||
: "userEnabled";
|
: "userEnabled";
|
||||||
|
|
||||||
|
@ -977,6 +1001,14 @@ var AddonManagerInternal = {
|
||||||
* The ID of the add-on
|
* The ID of the add-on
|
||||||
*/
|
*/
|
||||||
addStartupChange: function AMI_addStartupChange(aType, aID) {
|
addStartupChange: function AMI_addStartupChange(aType, aID) {
|
||||||
|
if (!aType || typeof aType != "string")
|
||||||
|
throw Components.Exception("aType must be a non-empty string",
|
||||||
|
Cr.NS_ERROR_INVALID_ARG);
|
||||||
|
|
||||||
|
if (!aID || typeof aID != "string")
|
||||||
|
throw Components.Exception("aID must be a non-empty string",
|
||||||
|
Cr.NS_ERROR_INVALID_ARG);
|
||||||
|
|
||||||
if (gStarted)
|
if (gStarted)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -998,6 +1030,14 @@ var AddonManagerInternal = {
|
||||||
* The ID of the add-on
|
* The ID of the add-on
|
||||||
*/
|
*/
|
||||||
removeStartupChange: function AMI_removeStartupChange(aType, aID) {
|
removeStartupChange: function AMI_removeStartupChange(aType, aID) {
|
||||||
|
if (!aType || typeof aType != "string")
|
||||||
|
throw Components.Exception("aType must be a non-empty string",
|
||||||
|
Cr.NS_ERROR_INVALID_ARG);
|
||||||
|
|
||||||
|
if (!aID || typeof aID != "string")
|
||||||
|
throw Components.Exception("aID must be a non-empty string",
|
||||||
|
Cr.NS_ERROR_INVALID_ARG);
|
||||||
|
|
||||||
if (gStarted)
|
if (gStarted)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -1015,6 +1055,10 @@ var AddonManagerInternal = {
|
||||||
* The method on the listeners to call
|
* The method on the listeners to call
|
||||||
*/
|
*/
|
||||||
callManagerListeners: function AMI_callManagerListeners(aMethod) {
|
callManagerListeners: function AMI_callManagerListeners(aMethod) {
|
||||||
|
if (!aMethod || typeof aMethod != "string")
|
||||||
|
throw Components.Exception("aMethod must be a non-empty string",
|
||||||
|
Cr.NS_ERROR_INVALID_ARG);
|
||||||
|
|
||||||
var args = Array.slice(arguments, 1);
|
var args = Array.slice(arguments, 1);
|
||||||
this.managerListeners.forEach(function(listener) {
|
this.managerListeners.forEach(function(listener) {
|
||||||
try {
|
try {
|
||||||
|
@ -1034,10 +1078,18 @@ var AddonManagerInternal = {
|
||||||
* @param aMethod
|
* @param aMethod
|
||||||
* The method on the listeners to call
|
* The method on the listeners to call
|
||||||
* @param aExtraListeners
|
* @param aExtraListeners
|
||||||
* An array of extra InstallListeners to also call
|
* An optional array of extra InstallListeners to also call
|
||||||
* @return false if any of the listeners returned false, true otherwise
|
* @return false if any of the listeners returned false, true otherwise
|
||||||
*/
|
*/
|
||||||
callInstallListeners: function AMI_callInstallListeners(aMethod, aExtraListeners) {
|
callInstallListeners: function AMI_callInstallListeners(aMethod, aExtraListeners) {
|
||||||
|
if (!aMethod || typeof aMethod != "string")
|
||||||
|
throw Components.Exception("aMethod must be a non-empty string",
|
||||||
|
Cr.NS_ERROR_INVALID_ARG);
|
||||||
|
|
||||||
|
if (aExtraListeners && !Array.isArray(aExtraListeners))
|
||||||
|
throw Components.Exception("aExtraListeners must be an array or null",
|
||||||
|
Cr.NS_ERROR_INVALID_ARG);
|
||||||
|
|
||||||
let result = true;
|
let result = true;
|
||||||
let listeners = this.installListeners;
|
let listeners = this.installListeners;
|
||||||
if (aExtraListeners)
|
if (aExtraListeners)
|
||||||
|
@ -1066,6 +1118,10 @@ var AddonManagerInternal = {
|
||||||
* The method on the listeners to call
|
* The method on the listeners to call
|
||||||
*/
|
*/
|
||||||
callAddonListeners: function AMI_callAddonListeners(aMethod) {
|
callAddonListeners: function AMI_callAddonListeners(aMethod) {
|
||||||
|
if (!aMethod || typeof aMethod != "string")
|
||||||
|
throw Components.Exception("aMethod must be a non-empty string",
|
||||||
|
Cr.NS_ERROR_INVALID_ARG);
|
||||||
|
|
||||||
var args = Array.slice(arguments, 1);
|
var args = Array.slice(arguments, 1);
|
||||||
this.addonListeners.forEach(function(listener) {
|
this.addonListeners.forEach(function(listener) {
|
||||||
try {
|
try {
|
||||||
|
@ -1083,17 +1139,25 @@ var AddonManagerInternal = {
|
||||||
* add-on only supports a single add-on being enabled at a time. This allows
|
* add-on only supports a single add-on being enabled at a time. This allows
|
||||||
* the providers to disable theirs if necessary.
|
* the providers to disable theirs if necessary.
|
||||||
*
|
*
|
||||||
* @param aId
|
* @param aID
|
||||||
* The id of the enabled add-on
|
* The ID of the enabled add-on
|
||||||
* @param aType
|
* @param aType
|
||||||
* The type of the enabled add-on
|
* The type of the enabled add-on
|
||||||
* @param aPendingRestart
|
* @param aPendingRestart
|
||||||
* A boolean indicating if the change will only take place the next
|
* A boolean indicating if the change will only take place the next
|
||||||
* time the application is restarted
|
* time the application is restarted
|
||||||
*/
|
*/
|
||||||
notifyAddonChanged: function AMI_notifyAddonChanged(aId, aType, aPendingRestart) {
|
notifyAddonChanged: function AMI_notifyAddonChanged(aID, aType, aPendingRestart) {
|
||||||
|
if (aID && typeof aID != "string")
|
||||||
|
throw Components.Exception("aID must be a string or null",
|
||||||
|
Cr.NS_ERROR_INVALID_ARG);
|
||||||
|
|
||||||
|
if (!aType || typeof aType != "string")
|
||||||
|
throw Components.Exception("aType must be a non-empty string",
|
||||||
|
Cr.NS_ERROR_INVALID_ARG);
|
||||||
|
|
||||||
this.providers.forEach(function(provider) {
|
this.providers.forEach(function(provider) {
|
||||||
callProvider(provider, "addonChanged", null, aId, aType, aPendingRestart);
|
callProvider(provider, "addonChanged", null, aID, aType, aPendingRestart);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -1116,8 +1180,8 @@ var AddonManagerInternal = {
|
||||||
* Function to call when operation is complete.
|
* Function to call when operation is complete.
|
||||||
*/
|
*/
|
||||||
updateAddonRepositoryData: function AMI_updateAddonRepositoryData(aCallback) {
|
updateAddonRepositoryData: function AMI_updateAddonRepositoryData(aCallback) {
|
||||||
if (!aCallback)
|
if (typeof aCallback != "function")
|
||||||
throw Components.Exception("Must specify aCallback",
|
throw Components.Exception("aCallback must be a function",
|
||||||
Cr.NS_ERROR_INVALID_ARG);
|
Cr.NS_ERROR_INVALID_ARG);
|
||||||
|
|
||||||
new AsyncObjectCaller(this.providers, "updateAddonRepositoryData", {
|
new AsyncObjectCaller(this.providers, "updateAddonRepositoryData", {
|
||||||
|
@ -1132,11 +1196,12 @@ var AddonManagerInternal = {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Asynchronously gets an AddonInstall for a URL.
|
* Asynchronously gets an AddonInstall for a URL.
|
||||||
*
|
*
|
||||||
* @param aUrl
|
* @param aUrl
|
||||||
* The url the add-on is located at
|
* The string represenation of the URL the add-on is located at
|
||||||
* @param aCallback
|
* @param aCallback
|
||||||
* A callback to pass the AddonInstall to
|
* A callback to pass the AddonInstall to
|
||||||
* @param aMimetype
|
* @param aMimetype
|
||||||
|
@ -1156,8 +1221,37 @@ var AddonManagerInternal = {
|
||||||
getInstallForURL: function AMI_getInstallForURL(aUrl, aCallback, aMimetype,
|
getInstallForURL: function AMI_getInstallForURL(aUrl, aCallback, aMimetype,
|
||||||
aHash, aName, aIconURL,
|
aHash, aName, aIconURL,
|
||||||
aVersion, aLoadGroup) {
|
aVersion, aLoadGroup) {
|
||||||
if (!aUrl || !aMimetype || !aCallback)
|
if (!aUrl || typeof aUrl != "string")
|
||||||
throw new TypeError("Invalid arguments");
|
throw Components.Exception("aURL must be a non-empty string",
|
||||||
|
Cr.NS_ERROR_INVALID_ARG);
|
||||||
|
|
||||||
|
if (typeof aCallback != "function")
|
||||||
|
throw Components.Exception("aCallback must be a function",
|
||||||
|
Cr.NS_ERROR_INVALID_ARG);
|
||||||
|
|
||||||
|
if (!aMimetype || typeof aMimetype != "string")
|
||||||
|
throw Components.Exception("aMimetype must be a non-empty string",
|
||||||
|
Cr.NS_ERROR_INVALID_ARG);
|
||||||
|
|
||||||
|
if (aHash && typeof aHash != "string")
|
||||||
|
throw Components.Exception("aHash must be a string or null",
|
||||||
|
Cr.NS_ERROR_INVALID_ARG);
|
||||||
|
|
||||||
|
if (aName && typeof aName != "string")
|
||||||
|
throw Components.Exception("aName must be a string or null",
|
||||||
|
Cr.NS_ERROR_INVALID_ARG);
|
||||||
|
|
||||||
|
if (aIconURL && typeof aIconURL != "string")
|
||||||
|
throw Components.Exception("aIconURL must be a string or null",
|
||||||
|
Cr.NS_ERROR_INVALID_ARG);
|
||||||
|
|
||||||
|
if (aVersion && typeof aVersion != "string")
|
||||||
|
throw Components.Exception("aVersion must be a string or null",
|
||||||
|
Cr.NS_ERROR_INVALID_ARG);
|
||||||
|
|
||||||
|
if (aLoadGroup && (!(aLoadGroup instanceof Ci.nsILoadGroup)))
|
||||||
|
throw Components.Exception("aLoadGroup must be a nsILoadGroup or null",
|
||||||
|
Cr.NS_ERROR_INVALID_ARG);
|
||||||
|
|
||||||
for (let provider of this.providers) {
|
for (let provider of this.providers) {
|
||||||
if (callProvider(provider, "supportsMimetype", false, aMimetype)) {
|
if (callProvider(provider, "supportsMimetype", false, aMimetype)) {
|
||||||
|
@ -1176,7 +1270,7 @@ var AddonManagerInternal = {
|
||||||
* Asynchronously gets an AddonInstall for an nsIFile.
|
* Asynchronously gets an AddonInstall for an nsIFile.
|
||||||
*
|
*
|
||||||
* @param aFile
|
* @param aFile
|
||||||
* the nsIFile where the add-on is located
|
* The nsIFile where the add-on is located
|
||||||
* @param aCallback
|
* @param aCallback
|
||||||
* A callback to pass the AddonInstall to
|
* A callback to pass the AddonInstall to
|
||||||
* @param aMimetype
|
* @param aMimetype
|
||||||
|
@ -1184,8 +1278,17 @@ var AddonManagerInternal = {
|
||||||
* @throws if the aFile or aCallback arguments are not specified
|
* @throws if the aFile or aCallback arguments are not specified
|
||||||
*/
|
*/
|
||||||
getInstallForFile: function AMI_getInstallForFile(aFile, aCallback, aMimetype) {
|
getInstallForFile: function AMI_getInstallForFile(aFile, aCallback, aMimetype) {
|
||||||
if (!aFile || !aCallback)
|
if (!(aFile instanceof Ci.nsIFile))
|
||||||
throw Cr.NS_ERROR_INVALID_ARG;
|
throw Components.Exception("aFile must be a nsIFile",
|
||||||
|
Cr.NS_ERROR_INVALID_ARG);
|
||||||
|
|
||||||
|
if (typeof aCallback != "function")
|
||||||
|
throw Components.Exception("aCallback must be a function",
|
||||||
|
Cr.NS_ERROR_INVALID_ARG);
|
||||||
|
|
||||||
|
if (aMimetype && typeof aMimetype != "string")
|
||||||
|
throw Components.Exception("aMimetype must be a string or null",
|
||||||
|
Cr.NS_ERROR_INVALID_ARG);
|
||||||
|
|
||||||
new AsyncObjectCaller(this.providers, "getInstallForFile", {
|
new AsyncObjectCaller(this.providers, "getInstallForFile", {
|
||||||
nextObject: function(aCaller, aProvider) {
|
nextObject: function(aCaller, aProvider) {
|
||||||
|
@ -1212,11 +1315,16 @@ var AddonManagerInternal = {
|
||||||
* An optional array of types to retrieve. Each type is a string name
|
* An optional array of types to retrieve. Each type is a string name
|
||||||
* @param aCallback
|
* @param aCallback
|
||||||
* A callback which will be passed an array of AddonInstalls
|
* A callback which will be passed an array of AddonInstalls
|
||||||
* @throws if the aCallback argument is not specified
|
* @throws If the aCallback argument is not specified
|
||||||
*/
|
*/
|
||||||
getInstallsByTypes: function AMI_getInstallsByTypes(aTypes, aCallback) {
|
getInstallsByTypes: function AMI_getInstallsByTypes(aTypes, aCallback) {
|
||||||
if (!aCallback)
|
if (aTypes && !Array.isArray(aTypes))
|
||||||
throw Cr.NS_ERROR_INVALID_ARG;
|
throw Components.Exception("aTypes must be an array or null",
|
||||||
|
Cr.NS_ERROR_INVALID_ARG);
|
||||||
|
|
||||||
|
if (typeof aCallback != "function")
|
||||||
|
throw Components.Exception("aCallback must be a function",
|
||||||
|
Cr.NS_ERROR_INVALID_ARG);
|
||||||
|
|
||||||
let installs = [];
|
let installs = [];
|
||||||
|
|
||||||
|
@ -1253,6 +1361,10 @@ var AddonManagerInternal = {
|
||||||
* @return true if installation is enabled for the mimetype
|
* @return true if installation is enabled for the mimetype
|
||||||
*/
|
*/
|
||||||
isInstallEnabled: function AMI_isInstallEnabled(aMimetype) {
|
isInstallEnabled: function AMI_isInstallEnabled(aMimetype) {
|
||||||
|
if (!aMimetype || typeof aMimetype != "string")
|
||||||
|
throw Components.Exception("aMimetype must be a non-empty string",
|
||||||
|
Cr.NS_ERROR_INVALID_ARG);
|
||||||
|
|
||||||
for (let provider of this.providers) {
|
for (let provider of this.providers) {
|
||||||
if (callProvider(provider, "supportsMimetype", false, aMimetype) &&
|
if (callProvider(provider, "supportsMimetype", false, aMimetype) &&
|
||||||
callProvider(provider, "isInstallEnabled"))
|
callProvider(provider, "isInstallEnabled"))
|
||||||
|
@ -1268,10 +1380,18 @@ var AddonManagerInternal = {
|
||||||
* @param aMimetype
|
* @param aMimetype
|
||||||
* The mimetype of the add-on
|
* The mimetype of the add-on
|
||||||
* @param aURI
|
* @param aURI
|
||||||
* The uri of the source, may be null
|
* The optional nsIURI of the source
|
||||||
* @return true if the source is allowed to install this mimetype
|
* @return true if the source is allowed to install this mimetype
|
||||||
*/
|
*/
|
||||||
isInstallAllowed: function AMI_isInstallAllowed(aMimetype, aURI) {
|
isInstallAllowed: function AMI_isInstallAllowed(aMimetype, aURI) {
|
||||||
|
if (!aMimetype || typeof aMimetype != "string")
|
||||||
|
throw Components.Exception("aMimetype must be a non-empty string",
|
||||||
|
Cr.NS_ERROR_INVALID_ARG);
|
||||||
|
|
||||||
|
if (aURI && !(aURI instanceof Ci.nsIURI))
|
||||||
|
throw Components.Exception("aURI must be a nsIURI or null",
|
||||||
|
Cr.NS_ERROR_INVALID_ARG);
|
||||||
|
|
||||||
for (let provider of this.providers) {
|
for (let provider of this.providers) {
|
||||||
if (callProvider(provider, "supportsMimetype", false, aMimetype) &&
|
if (callProvider(provider, "supportsMimetype", false, aMimetype) &&
|
||||||
callProvider(provider, "isInstallAllowed", null, aURI))
|
callProvider(provider, "isInstallAllowed", null, aURI))
|
||||||
|
@ -1287,9 +1407,9 @@ var AddonManagerInternal = {
|
||||||
* @param aMimetype
|
* @param aMimetype
|
||||||
* The mimetype of add-ons being installed
|
* The mimetype of add-ons being installed
|
||||||
* @param aSource
|
* @param aSource
|
||||||
* The nsIDOMWindow that started the installs
|
* The optional nsIDOMWindow that started the installs
|
||||||
* @param aURI
|
* @param aURI
|
||||||
* the nsIURI that started the installs
|
* The optional nsIURI that started the installs
|
||||||
* @param aInstalls
|
* @param aInstalls
|
||||||
* The array of AddonInstalls to be installed
|
* The array of AddonInstalls to be installed
|
||||||
*/
|
*/
|
||||||
|
@ -1297,6 +1417,22 @@ var AddonManagerInternal = {
|
||||||
aSource,
|
aSource,
|
||||||
aURI,
|
aURI,
|
||||||
aInstalls) {
|
aInstalls) {
|
||||||
|
if (!aMimetype || typeof aMimetype != "string")
|
||||||
|
throw Components.Exception("aMimetype must be a non-empty string",
|
||||||
|
Cr.NS_ERROR_INVALID_ARG);
|
||||||
|
|
||||||
|
if (aSource && !(aSource instanceof Ci.nsIDOMWindow))
|
||||||
|
throw Components.Exception("aSource must be a nsIDOMWindow or null",
|
||||||
|
Cr.NS_ERROR_INVALID_ARG);
|
||||||
|
|
||||||
|
if (aURI && !(aURI instanceof Ci.nsIURI))
|
||||||
|
throw Components.Exception("aURI must be a nsIURI or null",
|
||||||
|
Cr.NS_ERROR_INVALID_ARG);
|
||||||
|
|
||||||
|
if (!Array.isArray(aInstalls))
|
||||||
|
throw Components.Exception("aInstalls must be an array",
|
||||||
|
Cr.NS_ERROR_INVALID_ARG);
|
||||||
|
|
||||||
if (!("@mozilla.org/addons/web-install-listener;1" in Cc)) {
|
if (!("@mozilla.org/addons/web-install-listener;1" in Cc)) {
|
||||||
WARN("No web installer available, cancelling all installs");
|
WARN("No web installer available, cancelling all installs");
|
||||||
aInstalls.forEach(function(aInstall) {
|
aInstalls.forEach(function(aInstall) {
|
||||||
|
@ -1346,6 +1482,10 @@ var AddonManagerInternal = {
|
||||||
* The InstallListener to add
|
* The InstallListener to add
|
||||||
*/
|
*/
|
||||||
addInstallListener: function AMI_addInstallListener(aListener) {
|
addInstallListener: function AMI_addInstallListener(aListener) {
|
||||||
|
if (!aListener || typeof aListener != "object")
|
||||||
|
throw Components.Exception("aListener must be a InstallListener object",
|
||||||
|
Cr.NS_ERROR_INVALID_ARG);
|
||||||
|
|
||||||
if (!this.installListeners.some(function(i) { return i == aListener; }))
|
if (!this.installListeners.some(function(i) { return i == aListener; }))
|
||||||
this.installListeners.push(aListener);
|
this.installListeners.push(aListener);
|
||||||
},
|
},
|
||||||
|
@ -1357,6 +1497,10 @@ var AddonManagerInternal = {
|
||||||
* The InstallListener to remove
|
* The InstallListener to remove
|
||||||
*/
|
*/
|
||||||
removeInstallListener: function AMI_removeInstallListener(aListener) {
|
removeInstallListener: function AMI_removeInstallListener(aListener) {
|
||||||
|
if (!aListener || typeof aListener != "object")
|
||||||
|
throw Components.Exception("aListener must be a InstallListener object",
|
||||||
|
Cr.NS_ERROR_INVALID_ARG);
|
||||||
|
|
||||||
let pos = 0;
|
let pos = 0;
|
||||||
while (pos < this.installListeners.length) {
|
while (pos < this.installListeners.length) {
|
||||||
if (this.installListeners[pos] == aListener)
|
if (this.installListeners[pos] == aListener)
|
||||||
|
@ -1369,19 +1513,24 @@ var AddonManagerInternal = {
|
||||||
/**
|
/**
|
||||||
* Asynchronously gets an add-on with a specific ID.
|
* Asynchronously gets an add-on with a specific ID.
|
||||||
*
|
*
|
||||||
* @param aId
|
* @param aID
|
||||||
* The ID of the add-on to retrieve
|
* The ID of the add-on to retrieve
|
||||||
* @param aCallback
|
* @param aCallback
|
||||||
* The callback to pass the retrieved add-on to
|
* The callback to pass the retrieved add-on to
|
||||||
* @throws if the aId or aCallback arguments are not specified
|
* @throws if the aID or aCallback arguments are not specified
|
||||||
*/
|
*/
|
||||||
getAddonByID: function AMI_getAddonByID(aId, aCallback) {
|
getAddonByID: function AMI_getAddonByID(aID, aCallback) {
|
||||||
if (!aId || !aCallback)
|
if (!aID || typeof aID != "string")
|
||||||
throw Cr.NS_ERROR_INVALID_ARG;
|
throw Components.Exception("aID must be a non-empty string",
|
||||||
|
Cr.NS_ERROR_INVALID_ARG);
|
||||||
|
|
||||||
|
if (typeof aCallback != "function")
|
||||||
|
throw Components.Exception("aCallback must be a function",
|
||||||
|
Cr.NS_ERROR_INVALID_ARG);
|
||||||
|
|
||||||
new AsyncObjectCaller(this.providers, "getAddonByID", {
|
new AsyncObjectCaller(this.providers, "getAddonByID", {
|
||||||
nextObject: function(aCaller, aProvider) {
|
nextObject: function(aCaller, aProvider) {
|
||||||
callProvider(aProvider, "getAddonByID", null, aId, function(aAddon) {
|
callProvider(aProvider, "getAddonByID", null, aID, function(aAddon) {
|
||||||
if (aAddon)
|
if (aAddon)
|
||||||
safeCall(aCallback, aAddon);
|
safeCall(aCallback, aAddon);
|
||||||
else
|
else
|
||||||
|
@ -1405,9 +1554,13 @@ var AddonManagerInternal = {
|
||||||
* @throws if the aGUID or aCallback arguments are not specified
|
* @throws if the aGUID or aCallback arguments are not specified
|
||||||
*/
|
*/
|
||||||
getAddonBySyncGUID: function AMI_getAddonBySyncGUID(aGUID, aCallback) {
|
getAddonBySyncGUID: function AMI_getAddonBySyncGUID(aGUID, aCallback) {
|
||||||
if (!aGUID || !aCallback) {
|
if (!aGUID || typeof aGUID != "string")
|
||||||
throw Cr.NS_ERROR_INVALID_ARG;
|
throw Components.Exception("aGUID must be a non-empty string",
|
||||||
}
|
Cr.NS_ERROR_INVALID_ARG);
|
||||||
|
|
||||||
|
if (typeof aCallback != "function")
|
||||||
|
throw Components.Exception("aCallback must be a function",
|
||||||
|
Cr.NS_ERROR_INVALID_ARG);
|
||||||
|
|
||||||
new AsyncObjectCaller(this.providers, "getAddonBySyncGUID", {
|
new AsyncObjectCaller(this.providers, "getAddonBySyncGUID", {
|
||||||
nextObject: function(aCaller, aProvider) {
|
nextObject: function(aCaller, aProvider) {
|
||||||
|
@ -1429,21 +1582,26 @@ var AddonManagerInternal = {
|
||||||
/**
|
/**
|
||||||
* Asynchronously gets an array of add-ons.
|
* Asynchronously gets an array of add-ons.
|
||||||
*
|
*
|
||||||
* @param aIds
|
* @param aIDs
|
||||||
* The array of IDs to retrieve
|
* The array of IDs to retrieve
|
||||||
* @param aCallback
|
* @param aCallback
|
||||||
* The callback to pass an array of Addons to
|
* The callback to pass an array of Addons to
|
||||||
* @throws if the aId or aCallback arguments are not specified
|
* @throws if the aID or aCallback arguments are not specified
|
||||||
*/
|
*/
|
||||||
getAddonsByIDs: function AMI_getAddonsByIDs(aIds, aCallback) {
|
getAddonsByIDs: function AMI_getAddonsByIDs(aIDs, aCallback) {
|
||||||
if (!aIds || !aCallback)
|
if (!Array.isArray(aIDs))
|
||||||
throw Cr.NS_ERROR_INVALID_ARG;
|
throw Components.Exception("aIDs must be an array",
|
||||||
|
Cr.NS_ERROR_INVALID_ARG);
|
||||||
|
|
||||||
|
if (typeof aCallback != "function")
|
||||||
|
throw Components.Exception("aCallback must be a function",
|
||||||
|
Cr.NS_ERROR_INVALID_ARG);
|
||||||
|
|
||||||
let addons = [];
|
let addons = [];
|
||||||
|
|
||||||
new AsyncObjectCaller(aIds, null, {
|
new AsyncObjectCaller(aIDs, null, {
|
||||||
nextObject: function(aCaller, aId) {
|
nextObject: function(aCaller, aID) {
|
||||||
AddonManagerInternal.getAddonByID(aId, function(aAddon) {
|
AddonManagerInternal.getAddonByID(aID, function(aAddon) {
|
||||||
addons.push(aAddon);
|
addons.push(aAddon);
|
||||||
aCaller.callNext();
|
aCaller.callNext();
|
||||||
});
|
});
|
||||||
|
@ -1465,8 +1623,13 @@ var AddonManagerInternal = {
|
||||||
* @throws if the aCallback argument is not specified
|
* @throws if the aCallback argument is not specified
|
||||||
*/
|
*/
|
||||||
getAddonsByTypes: function AMI_getAddonsByTypes(aTypes, aCallback) {
|
getAddonsByTypes: function AMI_getAddonsByTypes(aTypes, aCallback) {
|
||||||
if (!aCallback)
|
if (aTypes && !Array.isArray(aTypes))
|
||||||
throw Cr.NS_ERROR_INVALID_ARG;
|
throw Components.Exception("aTypes must be an array or null",
|
||||||
|
Cr.NS_ERROR_INVALID_ARG);
|
||||||
|
|
||||||
|
if (typeof aCallback != "function")
|
||||||
|
throw Components.Exception("aCallback must be a function",
|
||||||
|
Cr.NS_ERROR_INVALID_ARG);
|
||||||
|
|
||||||
let addons = [];
|
let addons = [];
|
||||||
|
|
||||||
|
@ -1507,8 +1670,13 @@ var AddonManagerInternal = {
|
||||||
*/
|
*/
|
||||||
getAddonsWithOperationsByTypes:
|
getAddonsWithOperationsByTypes:
|
||||||
function AMI_getAddonsWithOperationsByTypes(aTypes, aCallback) {
|
function AMI_getAddonsWithOperationsByTypes(aTypes, aCallback) {
|
||||||
if (!aCallback)
|
if (aTypes && !Array.isArray(aTypes))
|
||||||
throw Cr.NS_ERROR_INVALID_ARG;
|
throw Components.Exception("aTypes must be an array or null",
|
||||||
|
Cr.NS_ERROR_INVALID_ARG);
|
||||||
|
|
||||||
|
if (typeof aCallback != "function")
|
||||||
|
throw Components.Exception("aCallback must be a function",
|
||||||
|
Cr.NS_ERROR_INVALID_ARG);
|
||||||
|
|
||||||
let addons = [];
|
let addons = [];
|
||||||
|
|
||||||
|
@ -1534,6 +1702,10 @@ var AddonManagerInternal = {
|
||||||
* The listener to add
|
* The listener to add
|
||||||
*/
|
*/
|
||||||
addManagerListener: function AMI_addManagerListener(aListener) {
|
addManagerListener: function AMI_addManagerListener(aListener) {
|
||||||
|
if (!aListener || typeof aListener != "object")
|
||||||
|
throw Components.Exception("aListener must be an AddonManagerListener object",
|
||||||
|
Cr.NS_ERROR_INVALID_ARG);
|
||||||
|
|
||||||
if (!this.managerListeners.some(function(i) { return i == aListener; }))
|
if (!this.managerListeners.some(function(i) { return i == aListener; }))
|
||||||
this.managerListeners.push(aListener);
|
this.managerListeners.push(aListener);
|
||||||
},
|
},
|
||||||
|
@ -1545,6 +1717,10 @@ var AddonManagerInternal = {
|
||||||
* The listener to remove
|
* The listener to remove
|
||||||
*/
|
*/
|
||||||
removeManagerListener: function AMI_removeManagerListener(aListener) {
|
removeManagerListener: function AMI_removeManagerListener(aListener) {
|
||||||
|
if (!aListener || typeof aListener != "object")
|
||||||
|
throw Components.Exception("aListener must be an AddonManagerListener object",
|
||||||
|
Cr.NS_ERROR_INVALID_ARG);
|
||||||
|
|
||||||
let pos = 0;
|
let pos = 0;
|
||||||
while (pos < this.managerListeners.length) {
|
while (pos < this.managerListeners.length) {
|
||||||
if (this.managerListeners[pos] == aListener)
|
if (this.managerListeners[pos] == aListener)
|
||||||
|
@ -1558,9 +1734,13 @@ var AddonManagerInternal = {
|
||||||
* Adds a new AddonListener if the listener is not already registered.
|
* Adds a new AddonListener if the listener is not already registered.
|
||||||
*
|
*
|
||||||
* @param aListener
|
* @param aListener
|
||||||
* The listener to add
|
* The AddonListener to add
|
||||||
*/
|
*/
|
||||||
addAddonListener: function AMI_addAddonListener(aListener) {
|
addAddonListener: function AMI_addAddonListener(aListener) {
|
||||||
|
if (!aListener || typeof aListener != "object")
|
||||||
|
throw Components.Exception("aListener must be an AddonListener object",
|
||||||
|
Cr.NS_ERROR_INVALID_ARG);
|
||||||
|
|
||||||
if (!this.addonListeners.some(function(i) { return i == aListener; }))
|
if (!this.addonListeners.some(function(i) { return i == aListener; }))
|
||||||
this.addonListeners.push(aListener);
|
this.addonListeners.push(aListener);
|
||||||
},
|
},
|
||||||
|
@ -1569,9 +1749,14 @@ var AddonManagerInternal = {
|
||||||
* Removes an AddonListener if the listener is registered.
|
* Removes an AddonListener if the listener is registered.
|
||||||
*
|
*
|
||||||
* @param aListener
|
* @param aListener
|
||||||
* The listener to remove
|
* The AddonListener to remove
|
||||||
*/
|
*/
|
||||||
removeAddonListener: function AMI_removeAddonListener(aListener) {
|
removeAddonListener: function AMI_removeAddonListener(aListener) {
|
||||||
|
if (!aListener || typeof aListener != "object")
|
||||||
|
throw Components.Exception("aListener must be an AddonListener object",
|
||||||
|
Cr.NS_ERROR_INVALID_ARG);
|
||||||
|
|
||||||
|
|
||||||
let pos = 0;
|
let pos = 0;
|
||||||
while (pos < this.addonListeners.length) {
|
while (pos < this.addonListeners.length) {
|
||||||
if (this.addonListeners[pos] == aListener)
|
if (this.addonListeners[pos] == aListener)
|
||||||
|
@ -1581,12 +1766,32 @@ var AddonManagerInternal = {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a new TypeListener if the listener is not already registered.
|
||||||
|
*
|
||||||
|
* @param aListener
|
||||||
|
* The TypeListener to add
|
||||||
|
*/
|
||||||
addTypeListener: function AMI_addTypeListener(aListener) {
|
addTypeListener: function AMI_addTypeListener(aListener) {
|
||||||
|
if (!aListener || typeof aListener != "object")
|
||||||
|
throw Components.Exception("aListener must be a TypeListener object",
|
||||||
|
Cr.NS_ERROR_INVALID_ARG);
|
||||||
|
|
||||||
if (!this.typeListeners.some(function(i) { return i == aListener; }))
|
if (!this.typeListeners.some(function(i) { return i == aListener; }))
|
||||||
this.typeListeners.push(aListener);
|
this.typeListeners.push(aListener);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes an TypeListener if the listener is registered.
|
||||||
|
*
|
||||||
|
* @param aListener
|
||||||
|
* The TypeListener to remove
|
||||||
|
*/
|
||||||
removeTypeListener: function AMI_removeTypeListener(aListener) {
|
removeTypeListener: function AMI_removeTypeListener(aListener) {
|
||||||
|
if (!aListener || typeof aListener != "object")
|
||||||
|
throw Components.Exception("aListener must be a TypeListener object",
|
||||||
|
Cr.NS_ERROR_INVALID_ARG);
|
||||||
|
|
||||||
let pos = 0;
|
let pos = 0;
|
||||||
while (pos < this.typeListeners.length) {
|
while (pos < this.typeListeners.length) {
|
||||||
if (this.typeListeners[pos] == aListener)
|
if (this.typeListeners[pos] == aListener)
|
||||||
|
@ -1707,8 +1912,8 @@ var AddonManagerPrivate = {
|
||||||
AddonManagerInternal.removeStartupChange(aType, aID);
|
AddonManagerInternal.removeStartupChange(aType, aID);
|
||||||
},
|
},
|
||||||
|
|
||||||
notifyAddonChanged: function AMP_notifyAddonChanged(aId, aType, aPendingRestart) {
|
notifyAddonChanged: function AMP_notifyAddonChanged(aID, aType, aPendingRestart) {
|
||||||
AddonManagerInternal.notifyAddonChanged(aId, aType, aPendingRestart);
|
AddonManagerInternal.notifyAddonChanged(aID, aType, aPendingRestart);
|
||||||
},
|
},
|
||||||
|
|
||||||
updateAddonAppDisabledStates: function AMP_updateAddonAppDisabledStates() {
|
updateAddonAppDisabledStates: function AMP_updateAddonAppDisabledStates() {
|
||||||
|
@ -1913,16 +2118,16 @@ var AddonManager = {
|
||||||
return AddonManagerInternal.startupChanges[aType].slice(0);
|
return AddonManagerInternal.startupChanges[aType].slice(0);
|
||||||
},
|
},
|
||||||
|
|
||||||
getAddonByID: function AM_getAddonByID(aId, aCallback) {
|
getAddonByID: function AM_getAddonByID(aID, aCallback) {
|
||||||
AddonManagerInternal.getAddonByID(aId, aCallback);
|
AddonManagerInternal.getAddonByID(aID, aCallback);
|
||||||
},
|
},
|
||||||
|
|
||||||
getAddonBySyncGUID: function AM_getAddonBySyncGUID(aId, aCallback) {
|
getAddonBySyncGUID: function AM_getAddonBySyncGUID(aGUID, aCallback) {
|
||||||
AddonManagerInternal.getAddonBySyncGUID(aId, aCallback);
|
AddonManagerInternal.getAddonBySyncGUID(aGUID, aCallback);
|
||||||
},
|
},
|
||||||
|
|
||||||
getAddonsByIDs: function AM_getAddonsByIDs(aIds, aCallback) {
|
getAddonsByIDs: function AM_getAddonsByIDs(aIDs, aCallback) {
|
||||||
AddonManagerInternal.getAddonsByIDs(aIds, aCallback);
|
AddonManagerInternal.getAddonsByIDs(aIDs, aCallback);
|
||||||
},
|
},
|
||||||
|
|
||||||
getAddonsWithOperationsByTypes:
|
getAddonsWithOperationsByTypes:
|
||||||
|
@ -1995,7 +2200,18 @@ var AddonManager = {
|
||||||
return AddonManagerInternal.addonTypes;
|
return AddonManagerInternal.addonTypes;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines whether an Addon should auto-update or not.
|
||||||
|
*
|
||||||
|
* @param aAddon
|
||||||
|
* The Addon representing the add-on
|
||||||
|
* @return true if the addon should auto-update, false otherwise.
|
||||||
|
*/
|
||||||
shouldAutoUpdate: function AM_shouldAutoUpdate(aAddon) {
|
shouldAutoUpdate: function AM_shouldAutoUpdate(aAddon) {
|
||||||
|
if (!aAddon || typeof aAddon != "object")
|
||||||
|
throw Components.Exception("aAddon must be specified",
|
||||||
|
Cr.NS_ERROR_INVALID_ARG);
|
||||||
|
|
||||||
if (!("applyBackgroundUpdates" in aAddon))
|
if (!("applyBackgroundUpdates" in aAddon))
|
||||||
return false;
|
return false;
|
||||||
if (aAddon.applyBackgroundUpdates == AddonManager.AUTOUPDATE_ENABLE)
|
if (aAddon.applyBackgroundUpdates == AddonManager.AUTOUPDATE_ENABLE)
|
||||||
|
|
|
@ -443,10 +443,10 @@ var gInstallingPage = {
|
||||||
actionItem.value = label;
|
actionItem.value = label;
|
||||||
},
|
},
|
||||||
|
|
||||||
onInstallEnded: function(aInstall) {
|
onInstallEnded: function(aInstall, aAddon) {
|
||||||
// Remember that this add-on was updated during startup
|
// Remember that this add-on was updated during startup
|
||||||
AddonManagerPrivate.addStartupChange(AddonManager.STARTUP_CHANGE_CHANGED,
|
AddonManagerPrivate.addStartupChange(AddonManager.STARTUP_CHANGE_CHANGED,
|
||||||
aInstall.id);
|
aAddon.id);
|
||||||
|
|
||||||
this.startNextInstall();
|
this.startNextInstall();
|
||||||
},
|
},
|
||||||
|
|
|
@ -61,7 +61,7 @@ function run_test_1() {
|
||||||
var testPlugin = get_test_plugin();
|
var testPlugin = get_test_plugin();
|
||||||
do_check_neq(testPlugin, null);
|
do_check_neq(testPlugin, null);
|
||||||
|
|
||||||
AddonManager.getAddonsByTypes("plugin", function(addons) {
|
AddonManager.getAddonsByTypes(["plugin"], function(addons) {
|
||||||
do_check_true(addons.length > 0);
|
do_check_true(addons.length > 0);
|
||||||
|
|
||||||
addons.forEach(function(p) {
|
addons.forEach(function(p) {
|
||||||
|
|
Загрузка…
Ссылка в новой задаче