зеркало из https://github.com/mozilla/gecko-dev.git
Bug 855544 - Implement a network monitor, r=dcamp,msucan
This commit is contained in:
Родитель
ea59580f90
Коммит
2253842238
|
@ -1077,6 +1077,12 @@ pref("devtools.debugger.ui.variables-searchbox-visible", false);
|
|||
// Enable the Profiler
|
||||
pref("devtools.profiler.enabled", true);
|
||||
|
||||
// Enable the Network Monitor
|
||||
pref("devtools.netmonitor.enabled", true);
|
||||
|
||||
// The default Network Monitor UI settings
|
||||
pref("devtools.netmonitor.panes-network-details-width", 450);
|
||||
|
||||
// Enable the Tilt inspector
|
||||
pref("devtools.tilt.enabled", true);
|
||||
pref("devtools.tilt.intro_transition", true);
|
||||
|
|
|
@ -31,6 +31,7 @@ Cu.import("resource://gre/modules/Services.jsm");
|
|||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/devtools/dbg-server.jsm");
|
||||
Cu.import("resource://gre/modules/devtools/dbg-client.jsm");
|
||||
Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js");
|
||||
Cu.import("resource:///modules/source-editor.jsm");
|
||||
Cu.import("resource:///modules/devtools/LayoutHelpers.jsm");
|
||||
Cu.import("resource:///modules/devtools/BreadcrumbsWidget.jsm");
|
||||
|
@ -38,12 +39,12 @@ Cu.import("resource:///modules/devtools/SideMenuWidget.jsm");
|
|||
Cu.import("resource:///modules/devtools/VariablesView.jsm");
|
||||
Cu.import("resource:///modules/devtools/ViewHelpers.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "Promise",
|
||||
"resource://gre/modules/commonjs/sdk/core/promise.js");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "Parser",
|
||||
"resource:///modules/devtools/Parser.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "NetworkHelper",
|
||||
"resource://gre/modules/devtools/NetworkHelper.jsm");
|
||||
|
||||
/**
|
||||
* Object defining the debugger controller components.
|
||||
*/
|
||||
|
@ -75,12 +76,12 @@ let DebuggerController = {
|
|||
*/
|
||||
startupDebugger: function DC_startupDebugger() {
|
||||
if (this._isInitialized) {
|
||||
return;
|
||||
return this._startup.promise;
|
||||
}
|
||||
this._isInitialized = true;
|
||||
window.removeEventListener("DOMContentLoaded", this.startupDebugger, true);
|
||||
|
||||
let deferred = Promise.defer();
|
||||
let deferred = this._startup = Promise.defer();
|
||||
|
||||
DebuggerView.initialize(() => {
|
||||
DebuggerView._isInitialized = true;
|
||||
|
@ -103,13 +104,14 @@ let DebuggerController = {
|
|||
* A promise that is resolved when the debugger finishes shutdown.
|
||||
*/
|
||||
shutdownDebugger: function DC__shutdownDebugger() {
|
||||
if (this._isDestroyed || !DebuggerView._isInitialized) {
|
||||
return;
|
||||
if (this._isDestroyed) {
|
||||
return this._shutdown.promise;
|
||||
}
|
||||
this._isDestroyed = true;
|
||||
this._startup = null;
|
||||
window.removeEventListener("unload", this.shutdownDebugger, true);
|
||||
|
||||
let deferred = Promise.defer();
|
||||
let deferred = this._shutdown = Promise.defer();
|
||||
|
||||
DebuggerView.destroy(() => {
|
||||
DebuggerView._isDestroyed = true;
|
||||
|
@ -128,14 +130,21 @@ let DebuggerController = {
|
|||
},
|
||||
|
||||
/**
|
||||
* Initializes a debugger client and connects it to the debugger server,
|
||||
* Initiates remote or chrome debugging based on the current target,
|
||||
* wiring event handlers as necessary.
|
||||
*
|
||||
* In case of a chrome debugger living in a different process, a socket
|
||||
* connection pipe is opened as well.
|
||||
*
|
||||
* @return object
|
||||
* A promise that is resolved when the debugger finishes connecting.
|
||||
*/
|
||||
connect: function DC_connect() {
|
||||
let deferred = Promise.defer();
|
||||
if (this._connection) {
|
||||
return this._connection.promise;
|
||||
}
|
||||
|
||||
let deferred = this._connection = Promise.defer();
|
||||
|
||||
if (!window._isChromeDebugger) {
|
||||
let target = this._target;
|
||||
|
@ -181,12 +190,13 @@ let DebuggerController = {
|
|||
this.client.removeListener("tabNavigated", this._onTabNavigated);
|
||||
this.client.removeListener("tabDetached", this._onTabDetached);
|
||||
|
||||
// When debugging content or a remote instance, the connection is closed by
|
||||
// When debugging local or a remote instance, the connection is closed by
|
||||
// the RemoteTarget.
|
||||
if (window._isChromeDebugger) {
|
||||
this.client.close();
|
||||
}
|
||||
|
||||
this._connection = null;
|
||||
this.client = null;
|
||||
this.tabClient = null;
|
||||
this.activeThread = null;
|
||||
|
@ -315,7 +325,16 @@ let DebuggerController = {
|
|||
return;
|
||||
}
|
||||
Services.startup.quit(Ci.nsIAppStartup.eAttemptQuit);
|
||||
}
|
||||
},
|
||||
|
||||
_isInitialized: false,
|
||||
_isDestroyed: false,
|
||||
_startup: null,
|
||||
_shutdown: null,
|
||||
_connection: null,
|
||||
client: null,
|
||||
tabClient: null,
|
||||
activeThread: null
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -911,7 +930,7 @@ StackFrames.prototype = {
|
|||
_addFrame: function SF__addFrame(aFrame) {
|
||||
let depth = aFrame.depth;
|
||||
let { url, line } = aFrame.where;
|
||||
let frameLocation = SourceUtils.convertToUnicode(window.unescape(url));
|
||||
let frameLocation = NetworkHelper.convertToUnicode(unescape(url));
|
||||
let frameTitle = StackFrameUtils.getFrameTitle(aFrame);
|
||||
|
||||
DebuggerView.StackFrames.addFrame(frameTitle, frameLocation, line, depth);
|
||||
|
@ -1191,7 +1210,7 @@ SourceScripts.prototype = {
|
|||
* Clears all the fetched sources from cache.
|
||||
*/
|
||||
clearCache: function SS_clearCache() {
|
||||
this._cache = new Map();
|
||||
this._cache.clear();
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -1631,100 +1650,31 @@ Breakpoints.prototype = {
|
|||
/**
|
||||
* Localization convenience methods.
|
||||
*/
|
||||
let L10N = {
|
||||
/**
|
||||
* L10N shortcut function.
|
||||
*
|
||||
* @param string aName
|
||||
* @return string
|
||||
*/
|
||||
getStr: function L10N_getStr(aName) {
|
||||
return this.stringBundle.GetStringFromName(aName);
|
||||
},
|
||||
|
||||
/**
|
||||
* L10N shortcut function.
|
||||
*
|
||||
* @param string aName
|
||||
* @param array aArray
|
||||
* @return string
|
||||
*/
|
||||
getFormatStr: function L10N_getFormatStr(aName, aArray) {
|
||||
return this.stringBundle.formatStringFromName(aName, aArray, aArray.length);
|
||||
}
|
||||
};
|
||||
|
||||
XPCOMUtils.defineLazyGetter(L10N, "stringBundle", function() {
|
||||
return Services.strings.createBundle(DBG_STRINGS_URI);
|
||||
});
|
||||
|
||||
XPCOMUtils.defineLazyGetter(L10N, "ellipsis", function() {
|
||||
return Services.prefs.getComplexValue("intl.ellipsis", Ci.nsIPrefLocalizedString).data;
|
||||
});
|
||||
let L10N = new ViewHelpers.L10N(DBG_STRINGS_URI);
|
||||
|
||||
/**
|
||||
* Shortcuts for accessing various debugger preferences.
|
||||
*/
|
||||
let Prefs = {
|
||||
/**
|
||||
* Helper method for getting a pref value.
|
||||
*
|
||||
* @param string aType
|
||||
* @param string aPrefName
|
||||
* @return any
|
||||
*/
|
||||
_get: function P__get(aType, aPrefName) {
|
||||
if (this[aPrefName] === undefined) {
|
||||
this[aPrefName] = Services.prefs["get" + aType + "Pref"](aPrefName);
|
||||
}
|
||||
return this[aPrefName];
|
||||
},
|
||||
|
||||
/**
|
||||
* Helper method for setting a pref value.
|
||||
*
|
||||
* @param string aType
|
||||
* @param string aPrefName
|
||||
* @param any aValue
|
||||
*/
|
||||
_set: function P__set(aType, aPrefName, aValue) {
|
||||
Services.prefs["set" + aType + "Pref"](aPrefName, aValue);
|
||||
this[aPrefName] = aValue;
|
||||
},
|
||||
|
||||
/**
|
||||
* Maps a property name to a pref, defining lazy getters and setters.
|
||||
*
|
||||
* @param string aType
|
||||
* @param string aPropertyName
|
||||
* @param string aPrefName
|
||||
*/
|
||||
map: function P_map(aType, aPropertyName, aPrefName) {
|
||||
Object.defineProperty(this, aPropertyName, {
|
||||
get: function() this._get(aType, aPrefName),
|
||||
set: function(aValue) this._set(aType, aPrefName, aValue)
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
Prefs.map("Char", "chromeDebuggingHost", "devtools.debugger.chrome-debugging-host");
|
||||
Prefs.map("Int", "chromeDebuggingPort", "devtools.debugger.chrome-debugging-port");
|
||||
Prefs.map("Int", "windowX", "devtools.debugger.ui.win-x");
|
||||
Prefs.map("Int", "windowY", "devtools.debugger.ui.win-y");
|
||||
Prefs.map("Int", "windowWidth", "devtools.debugger.ui.win-width");
|
||||
Prefs.map("Int", "windowHeight", "devtools.debugger.ui.win-height");
|
||||
Prefs.map("Int", "sourcesWidth", "devtools.debugger.ui.panes-sources-width");
|
||||
Prefs.map("Int", "instrumentsWidth", "devtools.debugger.ui.panes-instruments-width");
|
||||
Prefs.map("Bool", "pauseOnExceptions", "devtools.debugger.ui.pause-on-exceptions");
|
||||
Prefs.map("Bool", "panesVisibleOnStartup", "devtools.debugger.ui.panes-visible-on-startup");
|
||||
Prefs.map("Bool", "variablesSortingEnabled", "devtools.debugger.ui.variables-sorting-enabled");
|
||||
Prefs.map("Bool", "variablesOnlyEnumVisible", "devtools.debugger.ui.variables-only-enum-visible");
|
||||
Prefs.map("Bool", "variablesSearchboxVisible", "devtools.debugger.ui.variables-searchbox-visible");
|
||||
Prefs.map("Char", "remoteHost", "devtools.debugger.remote-host");
|
||||
Prefs.map("Int", "remotePort", "devtools.debugger.remote-port");
|
||||
Prefs.map("Bool", "remoteAutoConnect", "devtools.debugger.remote-autoconnect");
|
||||
Prefs.map("Int", "remoteConnectionRetries", "devtools.debugger.remote-connection-retries");
|
||||
Prefs.map("Int", "remoteTimeout", "devtools.debugger.remote-timeout");
|
||||
let Prefs = new ViewHelpers.Prefs("devtools.debugger", {
|
||||
chromeDebuggingHost: ["Char", "chrome-debugging-host"],
|
||||
chromeDebuggingPort: ["Int", "chrome-debugging-port"],
|
||||
windowX: ["Int", "ui.win-x"],
|
||||
windowY: ["Int", "ui.win-y"],
|
||||
windowWidth: ["Int", "ui.win-width"],
|
||||
windowHeight: ["Int", "ui.win-height"],
|
||||
sourcesWidth: ["Int", "ui.panes-sources-width"],
|
||||
instrumentsWidth: ["Int", "ui.panes-instruments-width"],
|
||||
pauseOnExceptions: ["Bool", "ui.pause-on-exceptions"],
|
||||
panesVisibleOnStartup: ["Bool", "ui.panes-visible-on-startup"],
|
||||
variablesSortingEnabled: ["Bool", "ui.variables-sorting-enabled"],
|
||||
variablesOnlyEnumVisible: ["Bool", "ui.variables-only-enum-visible"],
|
||||
variablesSearchboxVisible: ["Bool", "ui.variables-searchbox-visible"],
|
||||
remoteHost: ["Char", "remote-host"],
|
||||
remotePort: ["Int", "remote-port"],
|
||||
remoteAutoConnect: ["Bool", "remote-autoconnect"],
|
||||
remoteConnectionRetries: ["Int", "remote-connection-retries"],
|
||||
remoteTimeout: ["Int", "remote-timeout"]
|
||||
});
|
||||
|
||||
/**
|
||||
* Returns true if this is a remote debugger instance.
|
||||
|
|
|
@ -959,7 +959,7 @@ create({ constructor: SourcesView, proto: MenuContainer.prototype }, {
|
|||
* Utility functions for handling sources.
|
||||
*/
|
||||
let SourceUtils = {
|
||||
_labelsCache: new Map(),
|
||||
_labelsCache: new Map(), // Can't use WeakMaps because keys are strings.
|
||||
_groupsCache: new Map(),
|
||||
|
||||
/**
|
||||
|
@ -968,8 +968,8 @@ let SourceUtils = {
|
|||
* This should be done every time the content location changes.
|
||||
*/
|
||||
clearCache: function SU_clearCache() {
|
||||
this._labelsCache = new Map();
|
||||
this._groupsCache = new Map();
|
||||
this._labelsCache.clear();
|
||||
this._groupsCache.clear();
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -987,7 +987,7 @@ let SourceUtils = {
|
|||
}
|
||||
|
||||
let sourceLabel = this.trimUrl(aUrl);
|
||||
let unicodeLabel = this.convertToUnicode(window.unescape(sourceLabel));
|
||||
let unicodeLabel = NetworkHelper.convertToUnicode(unescape(sourceLabel));
|
||||
this._labelsCache.set(aUrl, unicodeLabel);
|
||||
return unicodeLabel;
|
||||
},
|
||||
|
@ -1036,7 +1036,7 @@ let SourceUtils = {
|
|||
}
|
||||
|
||||
let groupLabel = group.join(" ");
|
||||
let unicodeLabel = this.convertToUnicode(window.unescape(groupLabel));
|
||||
let unicodeLabel = NetworkHelper.convertToUnicode(unescape(groupLabel));
|
||||
this._groupsCache.set(aUrl, unicodeLabel)
|
||||
return unicodeLabel;
|
||||
},
|
||||
|
@ -1181,31 +1181,6 @@ let SourceUtils = {
|
|||
}
|
||||
// Give up.
|
||||
return aUrl.spec;
|
||||
},
|
||||
|
||||
/**
|
||||
* Convert a given string, encoded in a given character set, to unicode.
|
||||
*
|
||||
* @param string aString
|
||||
* A string.
|
||||
* @param string aCharset [optional]
|
||||
* A character set.
|
||||
* @return string
|
||||
* A unicode string.
|
||||
*/
|
||||
convertToUnicode: function SU_convertToUnicode(aString, aCharset) {
|
||||
// Decoding primitives.
|
||||
let converter = Cc["@mozilla.org/intl/scriptableunicodeconverter"]
|
||||
.createInstance(Ci.nsIScriptableUnicodeConverter);
|
||||
|
||||
try {
|
||||
if (aCharset) {
|
||||
converter.charset = aCharset;
|
||||
}
|
||||
return converter.ConvertToUnicode(aString);
|
||||
} catch(e) {
|
||||
return aString;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -37,11 +37,11 @@ ToolbarView.prototype = {
|
|||
let stepOverKey = LayoutHelpers.prettyKey(document.getElementById("stepOverKey"), true);
|
||||
let stepInKey = LayoutHelpers.prettyKey(document.getElementById("stepInKey"), true);
|
||||
let stepOutKey = LayoutHelpers.prettyKey(document.getElementById("stepOutKey"), true);
|
||||
this._resumeTooltip = L10N.getFormatStr("resumeButtonTooltip", [resumeKey]);
|
||||
this._pauseTooltip = L10N.getFormatStr("pauseButtonTooltip", [resumeKey]);
|
||||
this._stepOverTooltip = L10N.getFormatStr("stepOverTooltip", [stepOverKey]);
|
||||
this._stepInTooltip = L10N.getFormatStr("stepInTooltip", [stepInKey]);
|
||||
this._stepOutTooltip = L10N.getFormatStr("stepOutTooltip", [stepOutKey]);
|
||||
this._resumeTooltip = L10N.getFormatStr("resumeButtonTooltip", resumeKey);
|
||||
this._pauseTooltip = L10N.getFormatStr("pauseButtonTooltip", resumeKey);
|
||||
this._stepOverTooltip = L10N.getFormatStr("stepOverTooltip", stepOverKey);
|
||||
this._stepInTooltip = L10N.getFormatStr("stepInTooltip", stepInKey);
|
||||
this._stepOutTooltip = L10N.getFormatStr("stepOutTooltip", stepOutKey);
|
||||
|
||||
this._instrumentsPaneToggleButton.addEventListener("mousedown", this._onTogglePanesPressed, false);
|
||||
this._resumeButton.addEventListener("mousedown", this._onResumePressed, false);
|
||||
|
@ -645,7 +645,7 @@ let StackFrameUtils = {
|
|||
name = aEnv.type.charAt(0).toUpperCase() + aEnv.type.slice(1);
|
||||
}
|
||||
|
||||
let label = L10N.getFormatStr("scopeLabel", [name]);
|
||||
let label = L10N.getFormatStr("scopeLabel", name);
|
||||
switch (aEnv.type) {
|
||||
case "with":
|
||||
case "object":
|
||||
|
@ -714,15 +714,15 @@ FilterView.prototype = {
|
|||
this._variableOperatorButton.setAttribute("label", SEARCH_VARIABLE_FLAG);
|
||||
|
||||
this._globalOperatorLabel.setAttribute("value",
|
||||
L10N.getFormatStr("searchPanelGlobal", [this._globalSearchKey]));
|
||||
L10N.getFormatStr("searchPanelGlobal", this._globalSearchKey));
|
||||
this._functionOperatorLabel.setAttribute("value",
|
||||
L10N.getFormatStr("searchPanelFunction", [this._filteredFunctionsKey]));
|
||||
L10N.getFormatStr("searchPanelFunction", this._filteredFunctionsKey));
|
||||
this._tokenOperatorLabel.setAttribute("value",
|
||||
L10N.getFormatStr("searchPanelToken", [this._tokenSearchKey]));
|
||||
L10N.getFormatStr("searchPanelToken", this._tokenSearchKey));
|
||||
this._lineOperatorLabel.setAttribute("value",
|
||||
L10N.getFormatStr("searchPanelLine", [this._lineSearchKey]));
|
||||
L10N.getFormatStr("searchPanelLine", this._lineSearchKey));
|
||||
this._variableOperatorLabel.setAttribute("value",
|
||||
L10N.getFormatStr("searchPanelVariable", [this._variableSearchKey]));
|
||||
L10N.getFormatStr("searchPanelVariable", this._variableSearchKey));
|
||||
|
||||
// TODO: bug 806775
|
||||
// if (window._isChromeDebugger) {
|
||||
|
@ -753,10 +753,10 @@ FilterView.prototype = {
|
|||
let placeholder = "";
|
||||
switch (aView) {
|
||||
case DebuggerView.ChromeGlobals:
|
||||
placeholder = L10N.getFormatStr("emptyChromeGlobalsFilterText", [this._fileSearchKey]);
|
||||
placeholder = L10N.getFormatStr("emptyChromeGlobalsFilterText", this._fileSearchKey);
|
||||
break;
|
||||
case DebuggerView.Sources:
|
||||
placeholder = L10N.getFormatStr("emptyFilterText", [this._fileSearchKey]);
|
||||
placeholder = L10N.getFormatStr("emptyFilterText", this._fileSearchKey);
|
||||
break;
|
||||
}
|
||||
this._searchbox.setAttribute("placeholder", placeholder);
|
||||
|
|
|
@ -12,7 +12,6 @@ const STACK_FRAMES_SOURCE_URL_TRIM_SECTION = "center";
|
|||
const STACK_FRAMES_POPUP_SOURCE_URL_MAX_LENGTH = 32; // chars
|
||||
const STACK_FRAMES_POPUP_SOURCE_URL_TRIM_SECTION = "center";
|
||||
const STACK_FRAMES_SCROLL_DELAY = 100; // ms
|
||||
const PANES_APPEARANCE_DELAY = 50; // ms
|
||||
const BREAKPOINT_LINE_TOOLTIP_MAX_LENGTH = 1000; // chars
|
||||
const BREAKPOINT_CONDITIONAL_POPUP_POSITION = "before_start";
|
||||
const BREAKPOINT_CONDITIONAL_POPUP_OFFSET_X = 7; // px
|
||||
|
@ -416,67 +415,30 @@ let DebuggerView = {
|
|||
* @return boolean
|
||||
*/
|
||||
get instrumentsPaneHidden()
|
||||
this._instrumentsPaneToggleButton.hasAttribute("toggled"),
|
||||
this._instrumentsPane.hasAttribute("pane-collapsed"),
|
||||
|
||||
/**
|
||||
* Sets the instruments pane hidden or visible.
|
||||
*
|
||||
* @param object aFlags [optional]
|
||||
* An object containing some of the following boolean properties:
|
||||
* - visible: true if the pane should be shown, false for hidden
|
||||
* @param object aFlags
|
||||
* An object containing some of the following properties:
|
||||
* - visible: true if the pane should be shown, false to hide
|
||||
* - animated: true to display an animation on toggle
|
||||
* - delayed: true to wait a few cycles before toggle
|
||||
* - callback: a function to invoke when the toggle finishes
|
||||
*/
|
||||
toggleInstrumentsPane: function DV__toggleInstrumentsPane(aFlags = {}) {
|
||||
// Avoid useless toggles.
|
||||
if (aFlags.visible == !this.instrumentsPaneHidden) {
|
||||
if (aFlags.callback) aFlags.callback();
|
||||
return;
|
||||
}
|
||||
toggleInstrumentsPane: function DV__toggleInstrumentsPane(aFlags) {
|
||||
let pane = this._instrumentsPane;
|
||||
let button = this._instrumentsPaneToggleButton;
|
||||
|
||||
// Computes and sets the pane margins in order to hide or show it.
|
||||
function set() {
|
||||
if (aFlags.visible) {
|
||||
this._instrumentsPane.style.marginLeft = "0";
|
||||
this._instrumentsPane.style.marginRight = "0";
|
||||
this._instrumentsPaneToggleButton.removeAttribute("toggled");
|
||||
this._instrumentsPaneToggleButton.setAttribute("tooltiptext", this._collapsePaneString);
|
||||
} else {
|
||||
let margin = ~~(this._instrumentsPane.getAttribute("width")) + 1;
|
||||
this._instrumentsPane.style.marginLeft = -margin + "px";
|
||||
this._instrumentsPane.style.marginRight = -margin + "px";
|
||||
this._instrumentsPaneToggleButton.setAttribute("toggled", "true");
|
||||
this._instrumentsPaneToggleButton.setAttribute("tooltiptext", this._expandPaneString);
|
||||
}
|
||||
ViewHelpers.togglePane(aFlags, pane);
|
||||
|
||||
if (aFlags.animated) {
|
||||
// Displaying the panes may have the effect of triggering scrollbars to
|
||||
// appear in the source editor, which would render the currently
|
||||
// highlighted line to appear behind them in some cases.
|
||||
window.addEventListener("transitionend", function onEvent() {
|
||||
window.removeEventListener("transitionend", onEvent, false);
|
||||
DebuggerView.updateEditor();
|
||||
|
||||
// Invoke the callback when the transition ended.
|
||||
if (aFlags.callback) aFlags.callback();
|
||||
}, false);
|
||||
} else {
|
||||
// Invoke the callback immediately since there's no transition.
|
||||
if (aFlags.callback) aFlags.callback();
|
||||
}
|
||||
}
|
||||
|
||||
if (aFlags.animated) {
|
||||
this._instrumentsPane.setAttribute("animated", "");
|
||||
if (aFlags.visible) {
|
||||
button.removeAttribute("pane-collapsed");
|
||||
button.setAttribute("tooltiptext", this._collapsePaneString);
|
||||
} else {
|
||||
this._instrumentsPane.removeAttribute("animated");
|
||||
}
|
||||
|
||||
if (aFlags.delayed) {
|
||||
window.setTimeout(set.bind(this), PANES_APPEARANCE_DELAY);
|
||||
} else {
|
||||
set.call(this);
|
||||
button.setAttribute("pane-collapsed", "");
|
||||
button.setAttribute("tooltiptext", this._expandPaneString);
|
||||
}
|
||||
},
|
||||
|
||||
|
|
|
@ -273,7 +273,7 @@
|
|||
<splitter class="devtools-side-splitter"/>
|
||||
<vbox id="editor" flex="1"/>
|
||||
<splitter class="devtools-side-splitter"/>
|
||||
<vbox id="instruments-pane">
|
||||
<vbox id="instruments-pane" hidden="true">
|
||||
<vbox id="expressions"/>
|
||||
<splitter class="devtools-horizontal-splitter"/>
|
||||
<vbox id="variables" flex="1"/>
|
||||
|
|
|
@ -28,10 +28,13 @@ function test() {
|
|||
}
|
||||
|
||||
function testPanesState() {
|
||||
let instrumentsPane =
|
||||
gDebugger.document.getElementById("instruments-pane");
|
||||
let instrumentsPaneToggleButton =
|
||||
gDebugger.document.getElementById("instruments-pane-toggle");
|
||||
|
||||
ok(instrumentsPaneToggleButton.getAttribute("toggled"),
|
||||
ok(instrumentsPane.hasAttribute("pane-collapsed") &&
|
||||
instrumentsPaneToggleButton.hasAttribute("pane-collapsed"),
|
||||
"The debugger view instruments pane should initially be hidden.");
|
||||
is(gDebugger.Prefs.panesVisibleOnStartup, false,
|
||||
"The debugger view instruments pane should initially be preffed as hidden.");
|
||||
|
@ -54,7 +57,8 @@ function testInstrumentsPaneCollapse() {
|
|||
"The instruments pane has an incorrect right margin.");
|
||||
ok(!instrumentsPane.hasAttribute("animated"),
|
||||
"The instruments pane has an incorrect animated attribute.");
|
||||
ok(!instrumentsPaneToggleButton.getAttribute("toggled"),
|
||||
ok(!instrumentsPane.hasAttribute("pane-collapsed") &&
|
||||
!instrumentsPaneToggleButton.hasAttribute("pane-collapsed"),
|
||||
"The instruments pane should at this point be visible.");
|
||||
|
||||
gView.toggleInstrumentsPane({ visible: false, animated: true });
|
||||
|
@ -73,7 +77,8 @@ function testInstrumentsPaneCollapse() {
|
|||
"The instruments pane has an incorrect right margin after collapsing.");
|
||||
ok(instrumentsPane.hasAttribute("animated"),
|
||||
"The instruments pane has an incorrect attribute after an animated collapsing.");
|
||||
ok(instrumentsPaneToggleButton.hasAttribute("toggled"),
|
||||
ok(instrumentsPane.hasAttribute("pane-collapsed") &&
|
||||
instrumentsPaneToggleButton.hasAttribute("pane-collapsed"),
|
||||
"The instruments pane should not be visible after collapsing.");
|
||||
|
||||
gView.toggleInstrumentsPane({ visible: true, animated: false });
|
||||
|
@ -91,7 +96,8 @@ function testInstrumentsPaneCollapse() {
|
|||
"The instruments pane has an incorrect right margin after uncollapsing.");
|
||||
ok(!instrumentsPane.hasAttribute("animated"),
|
||||
"The instruments pane has an incorrect attribute after an unanimated uncollapsing.");
|
||||
ok(!instrumentsPaneToggleButton.getAttribute("toggled"),
|
||||
ok(!instrumentsPane.hasAttribute("pane-collapsed") &&
|
||||
!instrumentsPaneToggleButton.hasAttribute("pane-collapsed"),
|
||||
"The instruments pane should be visible again after uncollapsing.");
|
||||
}
|
||||
|
||||
|
@ -104,7 +110,8 @@ function testPanesStartupPref() {
|
|||
is(gDebugger.Prefs.panesVisibleOnStartup, false,
|
||||
"The debugger view panes should still initially be preffed as hidden.");
|
||||
|
||||
ok(!instrumentsPaneToggleButton.getAttribute("toggled"),
|
||||
ok(!instrumentsPane.hasAttribute("pane-collapsed") &&
|
||||
!instrumentsPaneToggleButton.hasAttribute("pane-collapsed"),
|
||||
"The debugger instruments pane should at this point be visible.");
|
||||
is(gDebugger.Prefs.panesVisibleOnStartup, false,
|
||||
"The debugger view panes should initially be preffed as hidden.");
|
||||
|
@ -115,7 +122,8 @@ function testPanesStartupPref() {
|
|||
gDebugger.DebuggerView.Options._toggleShowPanesOnStartup();
|
||||
|
||||
executeSoon(function() {
|
||||
ok(!instrumentsPaneToggleButton.getAttribute("toggled"),
|
||||
ok(!instrumentsPane.hasAttribute("pane-collapsed") &&
|
||||
!instrumentsPaneToggleButton.hasAttribute("pane-collapsed"),
|
||||
"The debugger instruments pane should at this point be visible.");
|
||||
is(gDebugger.Prefs.panesVisibleOnStartup, true,
|
||||
"The debugger view panes should now be preffed as visible.");
|
||||
|
@ -126,7 +134,8 @@ function testPanesStartupPref() {
|
|||
gDebugger.DebuggerView.Options._toggleShowPanesOnStartup();
|
||||
|
||||
executeSoon(function() {
|
||||
ok(!instrumentsPaneToggleButton.getAttribute("toggled"),
|
||||
ok(!instrumentsPane.hasAttribute("pane-collapsed") &&
|
||||
!instrumentsPaneToggleButton.hasAttribute("pane-collapsed"),
|
||||
"The debugger instruments pane should at this point be visible.");
|
||||
is(gDebugger.Prefs.panesVisibleOnStartup, false,
|
||||
"The debugger view panes should now be preffed as hidden.");
|
||||
|
|
|
@ -30,8 +30,8 @@ function testPause() {
|
|||
|
||||
let button = gDebugger.document.getElementById("resume");
|
||||
is(button.getAttribute("tooltiptext"),
|
||||
gL10N.getFormatStr("pauseButtonTooltip", [
|
||||
gLH.prettyKey(gDebugger.document.getElementById("resumeKey"))]),
|
||||
gL10N.getFormatStr("pauseButtonTooltip",
|
||||
gLH.prettyKey(gDebugger.document.getElementById("resumeKey"))),
|
||||
"Button tooltip should be pause when running.");
|
||||
|
||||
gDebugger.DebuggerController.activeThread.addOneTimeListener("paused", function() {
|
||||
|
@ -44,8 +44,8 @@ function testPause() {
|
|||
"Should be paused after an interrupt request.");
|
||||
|
||||
is(button.getAttribute("tooltiptext"),
|
||||
gL10N.getFormatStr("resumeButtonTooltip", [
|
||||
gLH.prettyKey(gDebugger.document.getElementById("resumeKey"))]),
|
||||
gL10N.getFormatStr("resumeButtonTooltip",
|
||||
gLH.prettyKey(gDebugger.document.getElementById("resumeKey"))),
|
||||
"Button tooltip should be resume when paused.");
|
||||
|
||||
is(frames.querySelectorAll(".dbg-stackframe").length, 0,
|
||||
|
@ -69,8 +69,8 @@ function testResume() {
|
|||
|
||||
let button = gDebugger.document.getElementById("resume");
|
||||
is(button.getAttribute("tooltiptext"),
|
||||
gL10N.getFormatStr("pauseButtonTooltip", [
|
||||
gLH.prettyKey(gDebugger.document.getElementById("resumeKey"))]),
|
||||
gL10N.getFormatStr("pauseButtonTooltip",
|
||||
gLH.prettyKey(gDebugger.document.getElementById("resumeKey"))),
|
||||
"Button tooltip should be pause when running.");
|
||||
|
||||
closeDebuggerAndFinish();
|
||||
|
|
|
@ -84,7 +84,7 @@ function testSourcesCache()
|
|||
"There should be " + TOTAL_SOURCES + " groups cached");
|
||||
|
||||
gPrevLabelsCache = gDebugger.SourceUtils._labelsCache;
|
||||
gPrevLabelsCache = gDebugger.SourceUtils._groupsCache;
|
||||
gPrevGroupsCache = gDebugger.SourceUtils._groupsCache;
|
||||
|
||||
fetchSources(function() {
|
||||
performReload(function() {
|
||||
|
@ -142,10 +142,10 @@ function testStateBeforeReload() {
|
|||
"There should be no sources present in the sources list during reload.");
|
||||
is(gControllerSources.getCache().length, 0,
|
||||
"The sources cache should be empty during reload.");
|
||||
isnot(gDebugger.SourceUtils._labelsCache, gPrevLabelsCache,
|
||||
"The labels cache has been refreshed during reload.")
|
||||
isnot(gDebugger.SourceUtils._groupsCache, gPrevGroupsCache,
|
||||
"The groups cache has been refreshed during reload.")
|
||||
is(gDebugger.SourceUtils._labelsCache, gPrevLabelsCache,
|
||||
"The labels cache has been refreshed during reload and no new objects were created.");
|
||||
is(gDebugger.SourceUtils._groupsCache, gPrevGroupsCache,
|
||||
"The groups cache has been refreshed during reload and no new objects were created.");
|
||||
is(gDebugger.SourceUtils._labelsCache.size, 0,
|
||||
"There should be no labels cached during reload");
|
||||
is(gDebugger.SourceUtils._groupsCache.size, 0,
|
||||
|
|
|
@ -9,7 +9,8 @@ this.EXPORTED_SYMBOLS = [
|
|||
"webConsoleDefinition",
|
||||
"debuggerDefinition",
|
||||
"inspectorDefinition",
|
||||
"styleEditorDefinition"
|
||||
"styleEditorDefinition",
|
||||
"netMonitorDefinition"
|
||||
];
|
||||
|
||||
const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
|
||||
|
@ -19,6 +20,7 @@ const debuggerProps = "chrome://browser/locale/devtools/debugger.properties";
|
|||
const styleEditorProps = "chrome://browser/locale/devtools/styleeditor.properties";
|
||||
const webConsoleProps = "chrome://browser/locale/devtools/webconsole.properties";
|
||||
const profilerProps = "chrome://browser/locale/devtools/profiler.properties";
|
||||
const netMonitorProps = "chrome://browser/locale/devtools/netmonitor.properties";
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
@ -43,6 +45,9 @@ XPCOMUtils.defineLazyModuleGetter(this, "InspectorPanel",
|
|||
XPCOMUtils.defineLazyModuleGetter(this, "ProfilerPanel",
|
||||
"resource:///modules/devtools/ProfilerPanel.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "NetMonitorPanel",
|
||||
"resource:///modules/devtools/NetMonitorPanel.jsm");
|
||||
|
||||
// Strings
|
||||
XPCOMUtils.defineLazyGetter(this, "webConsoleStrings",
|
||||
function() Services.strings.createBundle(webConsoleProps));
|
||||
|
@ -59,6 +64,9 @@ XPCOMUtils.defineLazyGetter(this, "inspectorStrings",
|
|||
XPCOMUtils.defineLazyGetter(this, "profilerStrings",
|
||||
function() Services.strings.createBundle(profilerProps));
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "netMonitorStrings",
|
||||
function() Services.strings.createBundle(netMonitorProps));
|
||||
|
||||
// Definitions
|
||||
let webConsoleDefinition = {
|
||||
id: "webconsole",
|
||||
|
@ -129,9 +137,9 @@ let styleEditorDefinition = {
|
|||
ordinal: 3,
|
||||
accesskey: l10n("open.accesskey", styleEditorStrings),
|
||||
modifiers: "shift",
|
||||
label: l10n("ToolboxStyleEditor.label", styleEditorStrings),
|
||||
icon: "chrome://browser/skin/devtools/tool-styleeditor.png",
|
||||
url: "chrome://browser/content/styleeditor.xul",
|
||||
label: l10n("ToolboxStyleEditor.label", styleEditorStrings),
|
||||
tooltip: l10n("ToolboxStyleEditor.tooltip", styleEditorStrings),
|
||||
|
||||
isTargetSupported: function(target) {
|
||||
|
@ -151,9 +159,9 @@ let profilerDefinition = {
|
|||
ordinal: 4,
|
||||
modifiers: "shift",
|
||||
killswitch: "devtools.profiler.enabled",
|
||||
icon: "chrome://browser/skin/devtools/tool-profiler.png",
|
||||
url: "chrome://browser/content/profiler.xul",
|
||||
label: l10n("profiler.label", profilerStrings),
|
||||
icon: "chrome://browser/skin/devtools/tool-profiler.png",
|
||||
tooltip: l10n("profiler.tooltip", profilerStrings),
|
||||
|
||||
isTargetSupported: function (target) {
|
||||
|
@ -166,12 +174,34 @@ let profilerDefinition = {
|
|||
}
|
||||
};
|
||||
|
||||
let netMonitorDefinition = {
|
||||
id: "netmonitor",
|
||||
accesskey: l10n("netmonitor.accesskey", netMonitorStrings),
|
||||
key: l10n("netmonitor.commandkey", netMonitorStrings),
|
||||
ordinal: 5,
|
||||
modifiers: osString == "Darwin" ? "accel,alt" : "accel,shift",
|
||||
killswitch: "devtools.netmonitor.enabled",
|
||||
icon: "chrome://browser/skin/devtools/tool-profiler.png",
|
||||
url: "chrome://browser/content/devtools/netmonitor.xul",
|
||||
label: l10n("netmonitor.label", netMonitorStrings),
|
||||
tooltip: l10n("netmonitor.tooltip", netMonitorStrings),
|
||||
|
||||
isTargetSupported: function(target) {
|
||||
return true;
|
||||
},
|
||||
|
||||
build: function(iframeWindow, toolbox) {
|
||||
let panel = new NetMonitorPanel(iframeWindow, toolbox);
|
||||
return panel.open();
|
||||
}
|
||||
};
|
||||
|
||||
this.defaultTools = [
|
||||
styleEditorDefinition,
|
||||
webConsoleDefinition,
|
||||
debuggerDefinition,
|
||||
inspectorDefinition,
|
||||
netMonitorDefinition
|
||||
];
|
||||
|
||||
if (Services.prefs.getBoolPref("devtools.profiler.enabled")) {
|
||||
|
|
|
@ -6,6 +6,10 @@ browser.jar:
|
|||
content/browser/devtools/widgets.css (shared/widgets/widgets.css)
|
||||
content/browser/devtools/markup-view.xhtml (markupview/markup-view.xhtml)
|
||||
content/browser/devtools/markup-view.css (markupview/markup-view.css)
|
||||
content/browser/devtools/netmonitor.xul (netmonitor/netmonitor.xul)
|
||||
content/browser/devtools/netmonitor.css (netmonitor/netmonitor.css)
|
||||
content/browser/devtools/netmonitor-controller.js (netmonitor/netmonitor-controller.js)
|
||||
content/browser/devtools/netmonitor-view.js (netmonitor/netmonitor-view.js)
|
||||
content/browser/NetworkPanel.xhtml (webconsole/NetworkPanel.xhtml)
|
||||
content/browser/devtools/webconsole.js (webconsole/webconsole.js)
|
||||
content/browser/devtools/webconsole.xul (webconsole/webconsole.xul)
|
||||
|
|
|
@ -15,6 +15,7 @@ DIRS += [
|
|||
'tilt',
|
||||
'scratchpad',
|
||||
'debugger',
|
||||
'netmonitor',
|
||||
'layoutview',
|
||||
'shared',
|
||||
'responsivedesign',
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
DEPTH = @DEPTH@
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
libs::
|
||||
$(NSINSTALL) $(srcdir)/*.jsm $(FINAL_TARGET)/modules/devtools
|
|
@ -0,0 +1,66 @@
|
|||
/* -*- Mode: javascript; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
"use strict";
|
||||
|
||||
const { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
|
||||
|
||||
this.EXPORTED_SYMBOLS = ["NetMonitorPanel"];
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource:///modules/devtools/EventEmitter.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "Promise",
|
||||
"resource://gre/modules/commonjs/sdk/core/promise.js");
|
||||
|
||||
function NetMonitorPanel(iframeWindow, toolbox) {
|
||||
this.panelWin = iframeWindow;
|
||||
this._toolbox = toolbox;
|
||||
|
||||
this._view = this.panelWin.NetMonitorView;
|
||||
this._controller = this.panelWin.NetMonitorController;
|
||||
this._controller._target = this.target;
|
||||
|
||||
EventEmitter.decorate(this);
|
||||
}
|
||||
|
||||
NetMonitorPanel.prototype = {
|
||||
/**
|
||||
* Open is effectively an asynchronous constructor.
|
||||
*
|
||||
* @return object
|
||||
* A Promise that is resolved when the NetMonitor completes opening.
|
||||
*/
|
||||
open: function NetMonitorPanel_open() {
|
||||
let promise;
|
||||
|
||||
// Local monitoring needs to make the target remote.
|
||||
if (!this.target.isRemote) {
|
||||
promise = this.target.makeRemote();
|
||||
} else {
|
||||
promise = Promise.resolve(this.target);
|
||||
}
|
||||
|
||||
return promise
|
||||
.then(() => this._controller.startupNetMonitor())
|
||||
.then(() => this._controller.connect())
|
||||
.then(() => {
|
||||
this.isReady = true;
|
||||
this.emit("ready");
|
||||
return this;
|
||||
})
|
||||
.then(null, function onError(aReason) {
|
||||
Cu.reportError("NetMonitorPanel open failed. " +
|
||||
reason.error + ": " + reason.message);
|
||||
});
|
||||
},
|
||||
|
||||
// DevToolPanel API
|
||||
get target() this._toolbox.target,
|
||||
|
||||
destroy: function() {
|
||||
this._controller.shutdownNetMonitor().then(() => this.emit("destroyed"));
|
||||
}
|
||||
};
|
|
@ -0,0 +1,6 @@
|
|||
# vim: set filetype=python:
|
||||
# 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/.
|
||||
|
||||
TEST_DIRS += ['test']
|
|
@ -0,0 +1,514 @@
|
|||
/* -*- Mode: javascript; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
"use strict";
|
||||
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
const Cu = Components.utils;
|
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js");
|
||||
Cu.import("resource:///modules/source-editor.jsm");
|
||||
Cu.import("resource:///modules/devtools/EventEmitter.jsm");
|
||||
Cu.import("resource:///modules/devtools/SideMenuWidget.jsm");
|
||||
Cu.import("resource:///modules/devtools/VariablesView.jsm");
|
||||
Cu.import("resource:///modules/devtools/ViewHelpers.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "NetworkHelper",
|
||||
"resource://gre/modules/devtools/NetworkHelper.jsm");
|
||||
|
||||
const NET_STRINGS_URI = "chrome://browser/locale/devtools/netmonitor.properties";
|
||||
const LISTENERS = [ "NetworkActivity" ];
|
||||
const NET_PREFS = { "NetworkMonitor.saveRequestAndResponseBodies": true };
|
||||
|
||||
/**
|
||||
* Object defining the network monitor controller components.
|
||||
*/
|
||||
let NetMonitorController = {
|
||||
/**
|
||||
* Initializes the view.
|
||||
*
|
||||
* @return object
|
||||
* A promise that is resolved when the monitor finishes startup.
|
||||
*/
|
||||
startupNetMonitor: function() {
|
||||
if (this._isInitialized) {
|
||||
return this._startup.promise;
|
||||
}
|
||||
this._isInitialized = true;
|
||||
|
||||
let deferred = this._startup = Promise.defer();
|
||||
|
||||
NetMonitorView.initialize(() => {
|
||||
NetMonitorView._isInitialized = true;
|
||||
deferred.resolve();
|
||||
});
|
||||
|
||||
return deferred.promise;
|
||||
},
|
||||
|
||||
/**
|
||||
* Destroys the view and disconnects the monitor client from the server.
|
||||
*
|
||||
* @return object
|
||||
* A promise that is resolved when the monitor finishes shutdown.
|
||||
*/
|
||||
shutdownNetMonitor: function() {
|
||||
if (this._isDestroyed) {
|
||||
return this._shutdown.promise;
|
||||
}
|
||||
this._isDestroyed = true;
|
||||
this._startup = null;
|
||||
|
||||
let deferred = this._shutdown = Promise.defer();
|
||||
|
||||
NetMonitorView.destroy(() => {
|
||||
NetMonitorView._isDestroyed = true;
|
||||
this.TargetEventsHandler.disconnect();
|
||||
this.NetworkEventsHandler.disconnect();
|
||||
|
||||
this.disconnect();
|
||||
deferred.resolve();
|
||||
});
|
||||
|
||||
return deferred.promise;
|
||||
},
|
||||
|
||||
/**
|
||||
* Initiates remote or chrome network monitoring based on the current target,
|
||||
* wiring event handlers as necessary.
|
||||
*
|
||||
* @return object
|
||||
* A promise that is resolved when the monitor finishes connecting.
|
||||
*/
|
||||
connect: function() {
|
||||
if (this._connection) {
|
||||
return this._connection.promise;
|
||||
}
|
||||
|
||||
let deferred = this._connection = Promise.defer();
|
||||
|
||||
let target = this._target;
|
||||
let { client, form } = target;
|
||||
if (target.chrome) {
|
||||
this._startChromeMonitoring(client, form.consoleActor, deferred.resolve);
|
||||
} else {
|
||||
this._startMonitoringTab(client, form, deferred.resolve);
|
||||
}
|
||||
|
||||
return deferred.promise;
|
||||
},
|
||||
|
||||
/**
|
||||
* Disconnects the debugger client and removes event handlers as necessary.
|
||||
*/
|
||||
disconnect: function() {
|
||||
// When debugging local or a remote instance, the connection is closed by
|
||||
// the RemoteTarget.
|
||||
this._connection = null;
|
||||
this.client = null;
|
||||
this.tabClient = null;
|
||||
this.webConsoleClient = null;
|
||||
},
|
||||
|
||||
/**
|
||||
* Sets up a monitoring session.
|
||||
*
|
||||
* @param DebuggerClient aClient
|
||||
* The debugger client.
|
||||
* @param object aTabGrip
|
||||
* The remote protocol grip of the tab.
|
||||
* @param function aCallback
|
||||
* A function to invoke once the client attached to the console client.
|
||||
*/
|
||||
_startMonitoringTab: function(aClient, aTabGrip, aCallback) {
|
||||
if (!aClient) {
|
||||
Cu.reportError("No client found!");
|
||||
return;
|
||||
}
|
||||
this.client = aClient;
|
||||
|
||||
aClient.attachTab(aTabGrip.actor, (aResponse, aTabClient) => {
|
||||
if (!aTabClient) {
|
||||
Cu.reportError("No tab client found!");
|
||||
return;
|
||||
}
|
||||
this.tabClient = aTabClient;
|
||||
|
||||
aClient.attachConsole(aTabGrip.consoleActor, LISTENERS, (aResponse, aWebConsoleClient) => {
|
||||
if (!aWebConsoleClient) {
|
||||
Cu.reportError("Couldn't attach to console: " + aResponse.error);
|
||||
return;
|
||||
}
|
||||
this.webConsoleClient = aWebConsoleClient;
|
||||
this.webConsoleClient.setPreferences(NET_PREFS, () => {
|
||||
this.TargetEventsHandler.connect();
|
||||
this.NetworkEventsHandler.connect();
|
||||
|
||||
if (aCallback) {
|
||||
aCallback();
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Sets up a chrome monitoring session.
|
||||
*
|
||||
* @param DebuggerClient aClient
|
||||
* The debugger client.
|
||||
* @param object aConsoleActor
|
||||
* The remote protocol grip of the chrome debugger.
|
||||
* @param function aCallback
|
||||
* A function to invoke once the client attached to the console client.
|
||||
*/
|
||||
_startChromeMonitoring: function(aClient, aConsoleActor, aCallback) {
|
||||
if (!aClient) {
|
||||
Cu.reportError("No client found!");
|
||||
return;
|
||||
}
|
||||
this.client = aClient;
|
||||
|
||||
aClient.attachConsole(aConsoleActor, LISTENERS, (aResponse, aWebConsoleClient) => {
|
||||
if (!aWebConsoleClient) {
|
||||
Cu.reportError("Couldn't attach to console: " + aResponse.error);
|
||||
return;
|
||||
}
|
||||
this.webConsoleClient = aWebConsoleClient;
|
||||
this.webConsoleClient.setPreferences(NET_PREFS, () => {
|
||||
this.TargetEventsHandler.connect();
|
||||
this.NetworkEventsHandler.connect();
|
||||
|
||||
if (aCallback) {
|
||||
aCallback();
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
_isInitialized: false,
|
||||
_isDestroyed: false,
|
||||
_startup: null,
|
||||
_shutdown: null,
|
||||
_connection: null,
|
||||
client: null,
|
||||
tabClient: null,
|
||||
webConsoleClient: null
|
||||
};
|
||||
|
||||
/**
|
||||
* Functions handling target-related lifetime events.
|
||||
*/
|
||||
function TargetEventsHandler() {
|
||||
this._onTabNavigated = this._onTabNavigated.bind(this);
|
||||
this._onTabDetached = this._onTabDetached.bind(this);
|
||||
}
|
||||
|
||||
TargetEventsHandler.prototype = {
|
||||
get target() NetMonitorController._target,
|
||||
get webConsoleClient() NetMonitorController.webConsoleClient,
|
||||
|
||||
/**
|
||||
* Listen for events emitted by the current tab target.
|
||||
*/
|
||||
connect: function() {
|
||||
dumpn("TargetEventsHandler is connecting...");
|
||||
this.target.on("close", this._onTabDetached);
|
||||
this.target.on("navigate", this._onTabNavigated);
|
||||
this.target.on("will-navigate", this._onTabNavigated);
|
||||
},
|
||||
|
||||
/**
|
||||
* Remove events emitted by the current tab target.
|
||||
*/
|
||||
disconnect: function() {
|
||||
if (!this.target) {
|
||||
return;
|
||||
}
|
||||
dumpn("TargetEventsHandler is disconnecting...");
|
||||
this.target.off("close", this._onTabDetached);
|
||||
this.target.off("navigate", this._onTabNavigated);
|
||||
this.target.off("will-navigate", this._onTabNavigated);
|
||||
},
|
||||
|
||||
/**
|
||||
* Called for each location change in the monitored tab.
|
||||
*
|
||||
* @param string aType
|
||||
* Packet type.
|
||||
* @param object aPacket
|
||||
* Packet received from the server.
|
||||
*/
|
||||
_onTabNavigated: function(aType, aPacket) {
|
||||
if (aType == "will-navigate") {
|
||||
NetMonitorView.RequestsMenu.reset();
|
||||
NetMonitorView.NetworkDetails.toggle(false);
|
||||
window.emit("NetMonitor:TargetWillNavigate");
|
||||
}
|
||||
if (aType == "navigate") {
|
||||
window.emit("NetMonitor:TargetNavigate");
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Called when the monitored tab is closed.
|
||||
*/
|
||||
_onTabDetached: function() {
|
||||
NetMonitorController.shutdownNetMonitor();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Functions handling target network events.
|
||||
*/
|
||||
function NetworkEventsHandler() {
|
||||
this._onNetworkEvent = this._onNetworkEvent.bind(this);
|
||||
this._onNetworkEventUpdate = this._onNetworkEventUpdate.bind(this);
|
||||
this._onRequestHeaders = this._onRequestHeaders.bind(this);
|
||||
this._onRequestCookies = this._onRequestCookies.bind(this);
|
||||
this._onRequestPostData = this._onRequestPostData.bind(this);
|
||||
this._onResponseHeaders = this._onResponseHeaders.bind(this);
|
||||
this._onResponseCookies = this._onResponseCookies.bind(this);
|
||||
this._onResponseContent = this._onResponseContent.bind(this);
|
||||
this._onEventTimings = this._onEventTimings.bind(this);
|
||||
}
|
||||
|
||||
NetworkEventsHandler.prototype = {
|
||||
get client() NetMonitorController._target.client,
|
||||
get webConsoleClient() NetMonitorController.webConsoleClient,
|
||||
|
||||
/**
|
||||
* Connect to the current target client.
|
||||
*/
|
||||
connect: function() {
|
||||
dumpn("NetworkEventsHandler is connecting...");
|
||||
this.client.addListener("networkEvent", this._onNetworkEvent);
|
||||
this.client.addListener("networkEventUpdate", this._onNetworkEventUpdate);
|
||||
},
|
||||
|
||||
/**
|
||||
* Disconnect from the client.
|
||||
*/
|
||||
disconnect: function() {
|
||||
if (!this.client) {
|
||||
return;
|
||||
}
|
||||
dumpn("NetworkEventsHandler is disconnecting...");
|
||||
this.client.removeListener("networkEvent", this._onNetworkEvent);
|
||||
this.client.removeListener("networkEventUpdate", this._onNetworkEventUpdate);
|
||||
},
|
||||
|
||||
/**
|
||||
* The "networkEvent" message type handler.
|
||||
*
|
||||
* @param string aType
|
||||
* Message type.
|
||||
* @param object aPacket
|
||||
* The message received from the server.
|
||||
*/
|
||||
_onNetworkEvent: function(aType, aPacket) {
|
||||
let { actor, startedDateTime, method, url } = aPacket.eventActor;
|
||||
NetMonitorView.RequestsMenu.addRequest(actor, startedDateTime, method, url);
|
||||
|
||||
window.emit("NetMonitor:NetworkEvent");
|
||||
},
|
||||
|
||||
/**
|
||||
* The "networkEventUpdate" message type handler.
|
||||
*
|
||||
* @param string aType
|
||||
* Message type.
|
||||
* @param object aPacket
|
||||
* The message received from the server.
|
||||
*/
|
||||
_onNetworkEventUpdate: function(aType, aPacket) {
|
||||
let actor = aPacket.from;
|
||||
|
||||
switch (aPacket.updateType) {
|
||||
case "requestHeaders":
|
||||
this.webConsoleClient.getRequestHeaders(actor, this._onRequestHeaders);
|
||||
window.emit("NetMonitor:NetworkEventUpdating:RequestHeaders");
|
||||
break;
|
||||
case "requestCookies":
|
||||
this.webConsoleClient.getRequestCookies(actor, this._onRequestCookies);
|
||||
window.emit("NetMonitor:NetworkEventUpdating:RequestCookies");
|
||||
break;
|
||||
case "requestPostData":
|
||||
this.webConsoleClient.getRequestPostData(actor, this._onRequestPostData);
|
||||
window.emit("NetMonitor:NetworkEventUpdating:RequestPostData");
|
||||
break;
|
||||
case "responseHeaders":
|
||||
this.webConsoleClient.getResponseHeaders(actor, this._onResponseHeaders);
|
||||
window.emit("NetMonitor:NetworkEventUpdating:ResponseHeaders");
|
||||
break;
|
||||
case "responseCookies":
|
||||
this.webConsoleClient.getResponseCookies(actor, this._onResponseCookies);
|
||||
window.emit("NetMonitor:NetworkEventUpdating:ResponseCookies");
|
||||
break;
|
||||
case "responseStart":
|
||||
NetMonitorView.RequestsMenu.updateRequest(aPacket.from, {
|
||||
httpVersion: aPacket.response.httpVersion,
|
||||
status: aPacket.response.status,
|
||||
statusText: aPacket.response.statusText,
|
||||
headersSize: aPacket.response.headersSize
|
||||
});
|
||||
window.emit("NetMonitor:NetworkEventUpdating:ResponseStart");
|
||||
break;
|
||||
case "responseContent":
|
||||
NetMonitorView.RequestsMenu.updateRequest(aPacket.from, {
|
||||
contentSize: aPacket.contentSize,
|
||||
mimeType: aPacket.mimeType
|
||||
});
|
||||
this.webConsoleClient.getResponseContent(actor, this._onResponseContent);
|
||||
window.emit("NetMonitor:NetworkEventUpdating:ResponseContent");
|
||||
break;
|
||||
case "eventTimings":
|
||||
NetMonitorView.RequestsMenu.updateRequest(aPacket.from, {
|
||||
totalTime: aPacket.totalTime
|
||||
});
|
||||
this.webConsoleClient.getEventTimings(actor, this._onEventTimings);
|
||||
window.emit("NetMonitor:NetworkEventUpdating:EventTimings");
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Handles additional information received for a "requestHeaders" packet.
|
||||
*
|
||||
* @param object aResponse
|
||||
* The message received from the server.
|
||||
*/
|
||||
_onRequestHeaders: function(aResponse) {
|
||||
NetMonitorView.RequestsMenu.updateRequest(aResponse.from, {
|
||||
requestHeaders: aResponse
|
||||
});
|
||||
window.emit("NetMonitor:NetworkEventUpdated:RequestHeaders");
|
||||
},
|
||||
|
||||
/**
|
||||
* Handles additional information received for a "requestCookies" packet.
|
||||
*
|
||||
* @param object aResponse
|
||||
* The message received from the server.
|
||||
*/
|
||||
_onRequestCookies: function(aResponse) {
|
||||
NetMonitorView.RequestsMenu.updateRequest(aResponse.from, {
|
||||
requestCookies: aResponse
|
||||
});
|
||||
window.emit("NetMonitor:NetworkEventUpdated:RequestCookies");
|
||||
},
|
||||
|
||||
/**
|
||||
* Handles additional information received for a "requestPostData" packet.
|
||||
*
|
||||
* @param object aResponse
|
||||
* The message received from the server.
|
||||
*/
|
||||
_onRequestPostData: function(aResponse) {
|
||||
NetMonitorView.RequestsMenu.updateRequest(aResponse.from, {
|
||||
requestPostData: aResponse
|
||||
});
|
||||
window.emit("NetMonitor:NetworkEventUpdated:RequestPostData");
|
||||
},
|
||||
|
||||
/**
|
||||
* Handles additional information received for a "responseHeaders" packet.
|
||||
*
|
||||
* @param object aResponse
|
||||
* The message received from the server.
|
||||
*/
|
||||
_onResponseHeaders: function(aResponse) {
|
||||
NetMonitorView.RequestsMenu.updateRequest(aResponse.from, {
|
||||
responseHeaders: aResponse
|
||||
});
|
||||
window.emit("NetMonitor:NetworkEventUpdated:ResponseHeaders");
|
||||
},
|
||||
|
||||
/**
|
||||
* Handles additional information received for a "responseCookies" packet.
|
||||
*
|
||||
* @param object aResponse
|
||||
* The message received from the server.
|
||||
*/
|
||||
_onResponseCookies: function(aResponse) {
|
||||
NetMonitorView.RequestsMenu.updateRequest(aResponse.from, {
|
||||
responseCookies: aResponse
|
||||
});
|
||||
window.emit("NetMonitor:NetworkEventUpdated:ResponseCookies");
|
||||
},
|
||||
|
||||
/**
|
||||
* Handles additional information received for a "responseContent" packet.
|
||||
*
|
||||
* @param object aResponse
|
||||
* The message received from the server.
|
||||
*/
|
||||
_onResponseContent: function(aResponse) {
|
||||
NetMonitorView.RequestsMenu.updateRequest(aResponse.from, {
|
||||
responseContent: aResponse
|
||||
});
|
||||
window.emit("NetMonitor:NetworkEventUpdated:ResponseContent");
|
||||
},
|
||||
|
||||
/**
|
||||
* Handles additional information received for a "eventTimings" packet.
|
||||
*
|
||||
* @param object aResponse
|
||||
* The message received from the server.
|
||||
*/
|
||||
_onEventTimings: function NEH__onEventTimings(aResponse) {
|
||||
NetMonitorView.RequestsMenu.updateRequest(aResponse.from, {
|
||||
eventTimings: aResponse
|
||||
});
|
||||
window.emit("NetMonitor:NetworkEventUpdated:EventTimings");
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Localization convenience methods.
|
||||
*/
|
||||
let L10N = new ViewHelpers.L10N(NET_STRINGS_URI);
|
||||
|
||||
/**
|
||||
* Shortcuts for accessing various network monitor preferences.
|
||||
*/
|
||||
let Prefs = new ViewHelpers.Prefs("devtools.netmonitor", {
|
||||
networkDetailsWidth: ["Int", "panes-network-details-width"]
|
||||
});
|
||||
|
||||
/**
|
||||
* Convenient way of emitting events from the panel window.
|
||||
*/
|
||||
EventEmitter.decorate(this);
|
||||
|
||||
/**
|
||||
* Preliminary setup for the NetMonitorController object.
|
||||
*/
|
||||
NetMonitorController.TargetEventsHandler = new TargetEventsHandler();
|
||||
NetMonitorController.NetworkEventsHandler = new NetworkEventsHandler();
|
||||
|
||||
/**
|
||||
* Export some properties to the global scope for easier access.
|
||||
*/
|
||||
Object.defineProperties(window, {
|
||||
"create": {
|
||||
get: function() ViewHelpers.create,
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Helper method for debugging.
|
||||
* @param string
|
||||
*/
|
||||
function dumpn(str) {
|
||||
if (wantLogging) {
|
||||
dump("NET-FRONTEND: " + str + "\n");
|
||||
}
|
||||
}
|
||||
|
||||
let wantLogging = Services.prefs.getBoolPref("devtools.debugger.log");
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -0,0 +1,8 @@
|
|||
/* vim:set ts=2 sw=2 sts=2 et: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#response-content-image-box {
|
||||
overflow: auto;
|
||||
}
|
|
@ -0,0 +1,269 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- 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/. -->
|
||||
<?xml-stylesheet href="chrome://browser/skin/" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://browser/content/devtools/widgets.css" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://browser/content/devtools/netmonitor.css" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://browser/skin/devtools/common.css" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://browser/skin/devtools/widgets.css" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://browser/skin/devtools/netmonitor.css" type="text/css"?>
|
||||
<!DOCTYPE window [
|
||||
<!ENTITY % netmonitorDTD SYSTEM "chrome://browser/locale/devtools/netmonitor.dtd">
|
||||
%netmonitorDTD;
|
||||
]>
|
||||
|
||||
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
<script type="text/javascript" src="netmonitor-controller.js"/>
|
||||
<script type="text/javascript" src="netmonitor-view.js"/>
|
||||
|
||||
<hbox id="body" flex="1">
|
||||
<vbox id="network-table" flex="1">
|
||||
<toolbar id="requests-menu-toolbar"
|
||||
class="devtools-toolbar"
|
||||
align="center">
|
||||
<label id="requests-menu-status-and-method-label"
|
||||
class="plain requests-menu-header requests-menu-status-and-method"
|
||||
value="&netmonitorUI.toolbar.method;"
|
||||
crop="end"/>
|
||||
<label id="requests-menu-file-label"
|
||||
class="plain requests-menu-header requests-menu-file"
|
||||
value="&netmonitorUI.toolbar.file;"
|
||||
crop="end"/>
|
||||
<label id="requests-menu-domain-label"
|
||||
class="plain requests-menu-header requests-menu-domain"
|
||||
value="&netmonitorUI.toolbar.domain;"
|
||||
crop="end"/>
|
||||
<label id="requests-menu-type-label"
|
||||
class="plain requests-menu-header requests-menu-type"
|
||||
value="&netmonitorUI.toolbar.type;"
|
||||
crop="end"/>
|
||||
<label id="requests-menu-size-label"
|
||||
class="plain requests-menu-header requests-menu-size"
|
||||
value="&netmonitorUI.toolbar.size;"
|
||||
crop="end"/>
|
||||
<label id="requests-menu-waterfall-label"
|
||||
class="plain requests-menu-header requests-menu-waterfall"
|
||||
value="&netmonitorUI.toolbar.waterfall;"
|
||||
crop="end"/>
|
||||
<spacer flex="1"/>
|
||||
<toolbarbutton id="details-pane-toggle"
|
||||
class="devtools-toolbarbutton"
|
||||
tooltiptext="&netmonitorUI.panesButton.tooltip;"
|
||||
tabindex="0"/>
|
||||
</toolbar>
|
||||
<label class="plain requests-menu-empty-notice"
|
||||
value="&netmonitorUI.emptyNotice;"/>
|
||||
<vbox id="requests-menu-contents" flex="1">
|
||||
<template id="requests-menu-item-template">
|
||||
<hbox class="requests-menu-item">
|
||||
<hbox class="requests-menu-subitem requests-menu-status-and-method"
|
||||
align="center">
|
||||
<hbox class="requests-menu-status"/>
|
||||
<label class="plain requests-menu-method"
|
||||
crop="end"
|
||||
flex="1"/>
|
||||
</hbox>
|
||||
<label class="plain requests-menu-subitem requests-menu-file"
|
||||
crop="end"/>
|
||||
<label class="plain requests-menu-subitem requests-menu-domain"
|
||||
crop="end"/>
|
||||
<label class="plain requests-menu-subitem requests-menu-type"
|
||||
crop="end"/>
|
||||
<label class="plain requests-menu-subitem requests-menu-size"
|
||||
crop="end"/>
|
||||
<hbox class="requests-menu-subitem requests-menu-waterfall"
|
||||
align="center"
|
||||
flex="1">
|
||||
<hbox class="requests-menu-timings"
|
||||
align="center">
|
||||
<hbox class="start requests-menu-timings-cap" hidden="true"/>
|
||||
<hbox class="end requests-menu-timings-cap" hidden="true"/>
|
||||
<label class="plain requests-menu-timings-total"/>
|
||||
</hbox>
|
||||
</hbox>
|
||||
</hbox>
|
||||
</template>
|
||||
</vbox>
|
||||
</vbox>
|
||||
|
||||
<splitter class="devtools-side-splitter"/>
|
||||
|
||||
<tabbox id="details-pane" class="devtools-sidebar-tabs" hidden="true">
|
||||
<tabs>
|
||||
<tab label="&netmonitorUI.tab.headers;"/>
|
||||
<tab label="&netmonitorUI.tab.cookies;"/>
|
||||
<tab label="&netmonitorUI.tab.params;"/>
|
||||
<tab label="&netmonitorUI.tab.response;"/>
|
||||
<tab label="&netmonitorUI.tab.timings;"/>
|
||||
</tabs>
|
||||
<tabpanels flex="1">
|
||||
<tabpanel id="headers-tabppanel"
|
||||
class="tabpanel-content">
|
||||
<vbox flex="1">
|
||||
<hbox id="headers-summary-url"
|
||||
class="tabpanel-summary-container"
|
||||
align="center">
|
||||
<label class="plain tabpanel-summary-label"
|
||||
value="&netmonitorUI.summary.url;"/>
|
||||
<label id="headers-summary-url-value"
|
||||
class="plain tabpanel-summary-value"
|
||||
crop="end"
|
||||
flex="1"/>
|
||||
</hbox>
|
||||
<hbox id="headers-summary-method"
|
||||
class="tabpanel-summary-container"
|
||||
align="center">
|
||||
<label class="plain tabpanel-summary-label"
|
||||
value="&netmonitorUI.summary.method;"/>
|
||||
<label id="headers-summary-method-value"
|
||||
class="plain tabpanel-summary-value"
|
||||
crop="end"
|
||||
flex="1"/>
|
||||
</hbox>
|
||||
<hbox id="headers-summary-status"
|
||||
class="tabpanel-summary-container"
|
||||
align="center">
|
||||
<label class="plain tabpanel-summary-label"
|
||||
value="&netmonitorUI.summary.status;"/>
|
||||
<hbox id="headers-summary-status-circle"
|
||||
class="requests-menu-status"/>
|
||||
<label id="headers-summary-status-value"
|
||||
class="plain tabpanel-summary-value"
|
||||
crop="end"
|
||||
flex="1"/>
|
||||
</hbox>
|
||||
<hbox id="headers-summary-version"
|
||||
class="tabpanel-summary-container"
|
||||
align="center">
|
||||
<label class="plain tabpanel-summary-label"
|
||||
value="&netmonitorUI.summary.version;"/>
|
||||
<label id="headers-summary-version-value"
|
||||
class="plain tabpanel-summary-value"
|
||||
crop="end"
|
||||
flex="1"/>
|
||||
</hbox>
|
||||
<vbox id="all-headers" flex="1"/>
|
||||
</vbox>
|
||||
</tabpanel>
|
||||
<tabpanel id="cookies-tabpanel"
|
||||
class="tabpanel-content">
|
||||
<vbox flex="1">
|
||||
<vbox id="all-cookies" flex="1"/>
|
||||
</vbox>
|
||||
</tabpanel>
|
||||
<tabpanel id="params-tabpanel"
|
||||
class="tabpanel-content">
|
||||
<vbox flex="1">
|
||||
<vbox id="request-params-box" flex="1" hidden="true">
|
||||
<vbox id="request-params" flex="1"/>
|
||||
</vbox>
|
||||
<vbox id="request-post-data-textarea-box" flex="1" hidden="true">
|
||||
<vbox id="request-post-data-textarea" flex="1"/>
|
||||
</vbox>
|
||||
</vbox>
|
||||
</tabpanel>
|
||||
<tabpanel id="response-tabpanel"
|
||||
class="tabpanel-content">
|
||||
<vbox flex="1">
|
||||
<vbox id="response-content-json-box" flex="1" hidden="true">
|
||||
<vbox id="response-content-json" flex="1"/>
|
||||
</vbox>
|
||||
<vbox id="response-content-textarea-box" flex="1" hidden="true">
|
||||
<vbox id="response-content-textarea" flex="1"/>
|
||||
</vbox>
|
||||
<vbox id="response-content-image-box" flex="1" hidden="true">
|
||||
<image id="response-content-image"/>
|
||||
<hbox>
|
||||
<label class="plain tabpanel-summary-label"
|
||||
value="&netmonitorUI.response.name;"/>
|
||||
<label id="response-content-image-name-value"
|
||||
class="plain tabpanel-summary-value"
|
||||
crop="end"
|
||||
flex="1"/>
|
||||
</hbox>
|
||||
<hbox>
|
||||
<label class="plain tabpanel-summary-label"
|
||||
value="&netmonitorUI.response.dimensions;"/>
|
||||
<label id="response-content-image-dimensions-value"
|
||||
class="plain tabpanel-summary-value"
|
||||
crop="end"
|
||||
flex="1"/>
|
||||
</hbox>
|
||||
<hbox>
|
||||
<label class="plain tabpanel-summary-label"
|
||||
value="&netmonitorUI.response.mime;"/>
|
||||
<label id="response-content-image-mime-value"
|
||||
class="plain tabpanel-summary-value"
|
||||
crop="end"
|
||||
flex="1"/>
|
||||
</hbox>
|
||||
<hbox>
|
||||
<label class="plain tabpanel-summary-label"
|
||||
value="&netmonitorUI.response.encoding;"/>
|
||||
<label id="response-content-image-encoding-value"
|
||||
class="plain tabpanel-summary-value"
|
||||
crop="end"
|
||||
flex="1"/>
|
||||
</hbox>
|
||||
</vbox>
|
||||
</vbox>
|
||||
</tabpanel>
|
||||
<tabpanel id="timings-tabpanel"
|
||||
class="tabpanel-content">
|
||||
<vbox flex="1">
|
||||
<hbox id="timings-summary-blocked"
|
||||
class="tabpanel-summary-container"
|
||||
align="center">
|
||||
<label class="plain tabpanel-summary-label"
|
||||
value="&netmonitorUI.timings.blocked;"/>
|
||||
<hbox class="requests-menu-timings-box blocked"/>
|
||||
<label class="plain requests-menu-timings-total"/>
|
||||
</hbox>
|
||||
<hbox id="timings-summary-dns"
|
||||
class="tabpanel-summary-container"
|
||||
align="center">
|
||||
<label class="plain tabpanel-summary-label"
|
||||
value="&netmonitorUI.timings.dns;"/>
|
||||
<hbox class="requests-menu-timings-box dns"/>
|
||||
<label class="plain requests-menu-timings-total"/>
|
||||
</hbox>
|
||||
<hbox id="timings-summary-connect"
|
||||
class="tabpanel-summary-container"
|
||||
align="center">
|
||||
<label class="plain tabpanel-summary-label"
|
||||
value="&netmonitorUI.timings.connect;"/>
|
||||
<hbox class="requests-menu-timings-box connect"/>
|
||||
<label class="plain requests-menu-timings-total"/>
|
||||
</hbox>
|
||||
<hbox id="timings-summary-send"
|
||||
class="tabpanel-summary-container"
|
||||
align="center">
|
||||
<label class="plain tabpanel-summary-label"
|
||||
value="&netmonitorUI.timings.send;"/>
|
||||
<hbox class="requests-menu-timings-box send"/>
|
||||
<label class="plain requests-menu-timings-total"/>
|
||||
</hbox>
|
||||
<hbox id="timings-summary-wait"
|
||||
class="tabpanel-summary-container"
|
||||
align="center">
|
||||
<label class="plain tabpanel-summary-label"
|
||||
value="&netmonitorUI.timings.wait;"/>
|
||||
<hbox class="requests-menu-timings-box wait"/>
|
||||
<label class="plain requests-menu-timings-total"/>
|
||||
</hbox>
|
||||
<hbox id="timings-summary-receive"
|
||||
class="tabpanel-summary-container"
|
||||
align="center">
|
||||
<label class="plain tabpanel-summary-label"
|
||||
value="&netmonitorUI.timings.receive;"/>
|
||||
<hbox class="requests-menu-timings-box receive"/>
|
||||
<label class="plain requests-menu-timings-total"/>
|
||||
</hbox>
|
||||
</vbox>
|
||||
</tabpanel>
|
||||
</tabpanels>
|
||||
</tabbox>
|
||||
</hbox>
|
||||
|
||||
</window>
|
|
@ -0,0 +1,43 @@
|
|||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
DEPTH = @DEPTH@
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
relativesrcdir = @relativesrcdir@
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
MOCHITEST_BROWSER_TESTS = \
|
||||
browser_net_aaa_leaktest.js \
|
||||
browser_net_simple-init.js \
|
||||
browser_net_page-nav.js \
|
||||
browser_net_prefs-and-l10n.js \
|
||||
browser_net_prefs-reload.js \
|
||||
browser_net_pane-collapse.js \
|
||||
browser_net_simple-request.js \
|
||||
browser_net_simple-request-data.js \
|
||||
browser_net_simple-request-details.js \
|
||||
browser_net_content-type.js \
|
||||
browser_net_status-codes.js \
|
||||
browser_net_post-data.js \
|
||||
head.js \
|
||||
$(NULL)
|
||||
|
||||
MOCHITEST_BROWSER_PAGES = \
|
||||
test-image.png \
|
||||
html_simple-test-page.html \
|
||||
html_navigate-test-page.html \
|
||||
html_content-type-test-page.html \
|
||||
html_status-codes-test-page.html \
|
||||
html_post-data-test-page.html \
|
||||
sjs_simple-test-server.sjs \
|
||||
sjs_content-type-test-server.sjs \
|
||||
sjs_status-codes-test-server.sjs \
|
||||
$(NULL)
|
||||
|
||||
MOCHITEST_BROWSER_FILES_PARTS = MOCHITEST_BROWSER_TESTS MOCHITEST_BROWSER_PAGES
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
|
@ -0,0 +1,28 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Tests if the network monitor leaks on initialization and sudden destruction.
|
||||
* You can also use this initialization format as a template for other tests.
|
||||
*/
|
||||
|
||||
function test() {
|
||||
initNetMonitor(SIMPLE_URL).then(([aTab, aDebuggee, aMonitor]) => {
|
||||
info("Starting test... ");
|
||||
|
||||
let { document, NetMonitorView, NetMonitorController } = aMonitor.panelWin;
|
||||
let { RequestsMenu, NetworkDetails } = NetMonitorView;
|
||||
|
||||
ok(aTab, "Should have a tab available.");
|
||||
ok(aDebuggee, "Should have a debuggee available.");
|
||||
ok(aMonitor, "Should have a network monitor pane available.");
|
||||
|
||||
ok(document, "Should have a document available.");
|
||||
ok(NetMonitorView, "Should have a NetMonitorView object available.");
|
||||
ok(NetMonitorController, "Should have a NetMonitorController object available.");
|
||||
ok(RequestsMenu, "Should have a RequestsMenu object available.");
|
||||
ok(NetworkDetails, "Should have a NetworkDetails object available.");
|
||||
|
||||
teardown(aMonitor).then(finish);
|
||||
});
|
||||
}
|
|
@ -0,0 +1,214 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Tests if different response content types are handled correctly.
|
||||
*/
|
||||
|
||||
function test() {
|
||||
initNetMonitor(CONTENT_TYPE_URL).then(([aTab, aDebuggee, aMonitor]) => {
|
||||
info("Starting test... ");
|
||||
|
||||
let { document, SourceEditor, NetMonitorView } = aMonitor.panelWin;
|
||||
let { RequestsMenu } = NetMonitorView;
|
||||
|
||||
RequestsMenu.lazyUpdate = false;
|
||||
|
||||
waitForNetworkEvents(aMonitor, 6).then(() => {
|
||||
verifyRequestItemTarget(RequestsMenu.getItemAtIndex(0),
|
||||
"GET", CONTENT_TYPE_SJS + "?fmt=xml", {
|
||||
status: 200,
|
||||
type: "xml",
|
||||
size: "0.04kb",
|
||||
time: true
|
||||
});
|
||||
verifyRequestItemTarget(RequestsMenu.getItemAtIndex(1),
|
||||
"GET", CONTENT_TYPE_SJS + "?fmt=css", {
|
||||
status: 200,
|
||||
type: "css",
|
||||
size: "0.03kb",
|
||||
time: true
|
||||
});
|
||||
verifyRequestItemTarget(RequestsMenu.getItemAtIndex(2),
|
||||
"GET", CONTENT_TYPE_SJS + "?fmt=js", {
|
||||
status: 200,
|
||||
type: "js",
|
||||
size: "0.03kb",
|
||||
time: true
|
||||
});
|
||||
verifyRequestItemTarget(RequestsMenu.getItemAtIndex(3),
|
||||
"GET", CONTENT_TYPE_SJS + "?fmt=json", {
|
||||
status: 200,
|
||||
type: "json",
|
||||
size: "0.03kb",
|
||||
time: true
|
||||
});
|
||||
verifyRequestItemTarget(RequestsMenu.getItemAtIndex(4),
|
||||
"GET", CONTENT_TYPE_SJS + "?fmt=bogus", {
|
||||
status: 404,
|
||||
type: "html",
|
||||
size: "0.02kb",
|
||||
time: true
|
||||
});
|
||||
verifyRequestItemTarget(RequestsMenu.getItemAtIndex(5),
|
||||
"GET", TEST_IMAGE, {
|
||||
status: 200,
|
||||
type: "png",
|
||||
size: "0.76kb",
|
||||
time: true
|
||||
});
|
||||
|
||||
EventUtils.sendMouseEvent({ type: "mousedown" },
|
||||
document.getElementById("details-pane-toggle"));
|
||||
EventUtils.sendMouseEvent({ type: "mousedown" },
|
||||
document.querySelectorAll("#details-pane tab")[3]);
|
||||
|
||||
testResponseTab("xml")
|
||||
.then(() => {
|
||||
RequestsMenu.selectedIndex = 1;
|
||||
return testResponseTab("css");
|
||||
})
|
||||
.then(() => {
|
||||
RequestsMenu.selectedIndex = 2;
|
||||
return testResponseTab("js");
|
||||
})
|
||||
.then(() => {
|
||||
RequestsMenu.selectedIndex = 3;
|
||||
return testResponseTab("json");
|
||||
})
|
||||
.then(() => {
|
||||
RequestsMenu.selectedIndex = 4;
|
||||
return testResponseTab("html");
|
||||
})
|
||||
.then(() => {
|
||||
RequestsMenu.selectedIndex = 5;
|
||||
return testResponseTab("png");
|
||||
})
|
||||
.then(() => {
|
||||
return teardown(aMonitor);
|
||||
})
|
||||
.then(finish);
|
||||
|
||||
function testResponseTab(aType) {
|
||||
let tab = document.querySelectorAll("#details-pane tab")[3];
|
||||
let tabpanel = document.querySelectorAll("#details-pane tabpanel")[3];
|
||||
|
||||
is(tab.getAttribute("selected"), "true",
|
||||
"The response tab in the network details pane should be selected.");
|
||||
|
||||
function checkVisibility(aBox) {
|
||||
is(tabpanel.querySelector("#response-content-json-box")
|
||||
.hasAttribute("hidden"), aBox != "json",
|
||||
"The response content json box doesn't have the intended visibility.");
|
||||
|
||||
is(tabpanel.querySelector("#response-content-textarea-box")
|
||||
.hasAttribute("hidden"), aBox != "textarea",
|
||||
"The response content textarea box doesn't have the intended visibility.");
|
||||
|
||||
is(tabpanel.querySelector("#response-content-image-box")
|
||||
.hasAttribute("hidden"), aBox != "image",
|
||||
"The response content image box doesn't have the intended visibility.");
|
||||
}
|
||||
|
||||
switch (aType) {
|
||||
case "xml": {
|
||||
checkVisibility("textarea");
|
||||
|
||||
return NetMonitorView.editor("#response-content-textarea").then((aEditor) => {
|
||||
is(aEditor.getText(), "<label value='greeting'>Hello XML!</label>",
|
||||
"The text shown in the source editor is incorrect for the xml request.");
|
||||
is(aEditor.getMode(), SourceEditor.MODES.HTML,
|
||||
"The mode active in the source editor is incorrect for the xml request.");
|
||||
});
|
||||
}
|
||||
case "css": {
|
||||
checkVisibility("textarea");
|
||||
|
||||
return NetMonitorView.editor("#response-content-textarea").then((aEditor) => {
|
||||
is(aEditor.getText(), "body:pre { content: 'Hello CSS!' }",
|
||||
"The text shown in the source editor is incorrect for the xml request.");
|
||||
is(aEditor.getMode(), SourceEditor.MODES.CSS,
|
||||
"The mode active in the source editor is incorrect for the xml request.");
|
||||
});
|
||||
}
|
||||
case "js": {
|
||||
checkVisibility("textarea");
|
||||
|
||||
return NetMonitorView.editor("#response-content-textarea").then((aEditor) => {
|
||||
is(aEditor.getText(), "function() { return 'Hello JS!'; }",
|
||||
"The text shown in the source editor is incorrect for the xml request.");
|
||||
is(aEditor.getMode(), SourceEditor.MODES.JAVASCRIPT,
|
||||
"The mode active in the source editor is incorrect for the xml request.");
|
||||
});
|
||||
}
|
||||
case "json": {
|
||||
checkVisibility("json");
|
||||
|
||||
is(tabpanel.querySelectorAll(".variables-view-scope").length, 1,
|
||||
"There should be 1 json scope displayed in this tabpanel.");
|
||||
is(tabpanel.querySelectorAll(".variables-view-property").length, 2,
|
||||
"There should be 2 json properties displayed in this tabpanel.");
|
||||
is(tabpanel.querySelectorAll(".variables-view-empty-notice").length, 0,
|
||||
"The empty notice should not be displayed in this tabpanel.");
|
||||
|
||||
let jsonScope = tabpanel.querySelectorAll(".variables-view-scope")[0];
|
||||
|
||||
is(jsonScope.querySelector(".name").getAttribute("value"),
|
||||
"JSON", "The json scope doesn't have the correct title.");
|
||||
|
||||
is(jsonScope.querySelectorAll(".variables-view-property .name")[0].getAttribute("value"),
|
||||
"greeting", "The first json property name was incorrect.");
|
||||
is(jsonScope.querySelectorAll(".variables-view-property .value")[0].getAttribute("value"),
|
||||
"\"Hello JSON!\"", "The first json property value was incorrect.");
|
||||
|
||||
is(jsonScope.querySelectorAll(".variables-view-property .name")[1].getAttribute("value"),
|
||||
"__proto__", "The second json property name was incorrect.");
|
||||
is(jsonScope.querySelectorAll(".variables-view-property .value")[1].getAttribute("value"),
|
||||
"[object Object]", "The second json property value was incorrect.");
|
||||
|
||||
return Promise.resolve();
|
||||
}
|
||||
case "html": {
|
||||
checkVisibility("textarea");
|
||||
|
||||
return NetMonitorView.editor("#response-content-textarea").then((aEditor) => {
|
||||
is(aEditor.getText(), "<blink>Not Found</blink>",
|
||||
"The text shown in the source editor is incorrect for the xml request.");
|
||||
is(aEditor.getMode(), SourceEditor.MODES.HTML,
|
||||
"The mode active in the source editor is incorrect for the xml request.");
|
||||
});
|
||||
}
|
||||
case "png": {
|
||||
checkVisibility("image");
|
||||
|
||||
let imageNode = tabpanel.querySelector("#response-content-image");
|
||||
let deferred = Promise.defer();
|
||||
|
||||
imageNode.addEventListener("load", function onLoad() {
|
||||
imageNode.removeEventListener("load", onLoad);
|
||||
|
||||
is(tabpanel.querySelector("#response-content-image-name-value")
|
||||
.getAttribute("value"), "test-image.png",
|
||||
"The image name info isn't correct.");
|
||||
is(tabpanel.querySelector("#response-content-image-mime-value")
|
||||
.getAttribute("value"), "image/png",
|
||||
"The image mime info isn't correct.");
|
||||
is(tabpanel.querySelector("#response-content-image-encoding-value")
|
||||
.getAttribute("value"), "base64",
|
||||
"The image encoding info isn't correct.");
|
||||
is(tabpanel.querySelector("#response-content-image-dimensions-value")
|
||||
.getAttribute("value"), "16 x 16",
|
||||
"The image dimensions info isn't correct.");
|
||||
|
||||
deferred.resolve();
|
||||
});
|
||||
|
||||
return deferred.promise;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
aDebuggee.performRequests();
|
||||
});
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Tests if page navigation ("close", "navigate", etc.) triggers an appropriate
|
||||
* action in the network monitor.
|
||||
*/
|
||||
|
||||
function test() {
|
||||
initNetMonitor(SIMPLE_URL).then(([aTab, aDebuggee, aMonitor]) => {
|
||||
info("Starting test... ");
|
||||
|
||||
testNavigate(() => testNavigateBack(() => testClose(() => finish())));
|
||||
|
||||
function testNavigate(aCallback) {
|
||||
info("Navigating forward...");
|
||||
|
||||
aMonitor.panelWin.once("NetMonitor:TargetWillNavigate", () => {
|
||||
is(aDebuggee.location, SIMPLE_URL,
|
||||
"Target started navigating to the correct location.");
|
||||
|
||||
aMonitor.panelWin.once("NetMonitor:TargetNavigate", () => {
|
||||
is(aDebuggee.location, NAVIGATE_URL,
|
||||
"Target finished navigating to the correct location.");
|
||||
|
||||
aCallback();
|
||||
});
|
||||
});
|
||||
|
||||
aDebuggee.location = NAVIGATE_URL;
|
||||
}
|
||||
|
||||
function testNavigateBack(aCallback) {
|
||||
info("Navigating backward...");
|
||||
|
||||
aMonitor.panelWin.once("NetMonitor:TargetWillNavigate", () => {
|
||||
is(aDebuggee.location, NAVIGATE_URL,
|
||||
"Target started navigating back to the previous location.");
|
||||
|
||||
aMonitor.panelWin.once("NetMonitor:TargetNavigate", () => {
|
||||
is(aDebuggee.location, SIMPLE_URL,
|
||||
"Target finished navigating back to the previous location.");
|
||||
|
||||
aCallback();
|
||||
});
|
||||
});
|
||||
|
||||
aDebuggee.location = SIMPLE_URL;
|
||||
}
|
||||
|
||||
function testClose(aCallback) {
|
||||
info("Closing...");
|
||||
|
||||
aMonitor.once("destroyed", () => {
|
||||
ok(!aMonitor._controller.client,
|
||||
"There shouldn't be a client available after destruction.");
|
||||
ok(!aMonitor._controller.tabClient,
|
||||
"There shouldn't be a tabClient available after destruction.");
|
||||
ok(!aMonitor._controller.webConsoleClient,
|
||||
"There shouldn't be a webConsoleClient available after destruction.");
|
||||
|
||||
aCallback();
|
||||
});
|
||||
|
||||
removeTab(aTab);
|
||||
}
|
||||
});
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Tests if the network monitor panes collapse properly.
|
||||
*/
|
||||
|
||||
function test() {
|
||||
initNetMonitor(SIMPLE_URL).then(([aTab, aDebuggee, aMonitor]) => {
|
||||
info("Starting test... ");
|
||||
|
||||
let { document, Prefs, NetMonitorView } = aMonitor.panelWin;
|
||||
let detailsPane = document.getElementById("details-pane");
|
||||
let detailsPaneToggleButton = document.getElementById("details-pane-toggle");
|
||||
|
||||
ok(detailsPane.hasAttribute("pane-collapsed") &&
|
||||
detailsPaneToggleButton.hasAttribute("pane-collapsed"),
|
||||
"The details pane should initially be hidden.");
|
||||
|
||||
NetMonitorView.toggleDetailsPane({ visible: true, animated: false });
|
||||
|
||||
let width = ~~(detailsPane.getAttribute("width"));
|
||||
is(width, Prefs.networkDetailsWidth,
|
||||
"The details pane has an incorrect width.");
|
||||
is(detailsPane.style.marginLeft, "0px",
|
||||
"The details pane has an incorrect left margin.");
|
||||
is(detailsPane.style.marginRight, "0px",
|
||||
"The details pane has an incorrect right margin.");
|
||||
ok(!detailsPane.hasAttribute("animated"),
|
||||
"The details pane has an incorrect animated attribute.");
|
||||
ok(!detailsPane.hasAttribute("pane-collapsed") &&
|
||||
!detailsPaneToggleButton.hasAttribute("pane-collapsed"),
|
||||
"The details pane should at this point be visible.");
|
||||
|
||||
NetMonitorView.toggleDetailsPane({ visible: false, animated: true });
|
||||
|
||||
let margin = -(width + 1) + "px";
|
||||
is(width, Prefs.networkDetailsWidth,
|
||||
"The details pane has an incorrect width after collapsing.");
|
||||
is(detailsPane.style.marginLeft, margin,
|
||||
"The details pane has an incorrect left margin after collapsing.");
|
||||
is(detailsPane.style.marginRight, margin,
|
||||
"The details pane has an incorrect right margin after collapsing.");
|
||||
ok(detailsPane.hasAttribute("animated"),
|
||||
"The details pane has an incorrect attribute after an animated collapsing.");
|
||||
ok(detailsPane.hasAttribute("pane-collapsed") &&
|
||||
detailsPaneToggleButton.hasAttribute("pane-collapsed"),
|
||||
"The details pane should not be visible after collapsing.");
|
||||
|
||||
NetMonitorView.toggleDetailsPane({ visible: true, animated: false });
|
||||
|
||||
is(width, Prefs.networkDetailsWidth,
|
||||
"The details pane has an incorrect width after uncollapsing.");
|
||||
is(detailsPane.style.marginLeft, "0px",
|
||||
"The details pane has an incorrect left margin after uncollapsing.");
|
||||
is(detailsPane.style.marginRight, "0px",
|
||||
"The details pane has an incorrect right margin after uncollapsing.");
|
||||
ok(!detailsPane.hasAttribute("animated"),
|
||||
"The details pane has an incorrect attribute after an unanimated uncollapsing.");
|
||||
ok(!detailsPane.hasAttribute("pane-collapsed") &&
|
||||
!detailsPaneToggleButton.hasAttribute("pane-collapsed"),
|
||||
"The details pane should be visible again after uncollapsing.");
|
||||
|
||||
teardown(aMonitor).then(finish);
|
||||
});
|
||||
}
|
|
@ -0,0 +1,150 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Tests if the POST requests display the correct information in the UI.
|
||||
*/
|
||||
|
||||
function test() {
|
||||
initNetMonitor(POST_DATA_URL).then(([aTab, aDebuggee, aMonitor]) => {
|
||||
info("Starting test... ");
|
||||
|
||||
let { document, L10N, SourceEditor, NetMonitorView } = aMonitor.panelWin;
|
||||
let { RequestsMenu, NetworkDetails } = NetMonitorView;
|
||||
|
||||
RequestsMenu.lazyUpdate = false;
|
||||
NetworkDetails._params.lazyEmpty = false;
|
||||
|
||||
waitForNetworkEvents(aMonitor, 0, 2).then(() => {
|
||||
verifyRequestItemTarget(RequestsMenu.getItemAtIndex(0),
|
||||
"POST", SIMPLE_SJS + "?foo=bar&baz=42&type=urlencoded", {
|
||||
status: 200,
|
||||
type: "plain",
|
||||
size: "0.01kb",
|
||||
time: true
|
||||
});
|
||||
verifyRequestItemTarget(RequestsMenu.getItemAtIndex(1),
|
||||
"POST", SIMPLE_SJS + "?foo=bar&baz=42&type=multipart", {
|
||||
status: 200,
|
||||
type: "plain",
|
||||
size: "0.01kb",
|
||||
time: true
|
||||
});
|
||||
|
||||
EventUtils.sendMouseEvent({ type: "mousedown" },
|
||||
document.getElementById("details-pane-toggle"));
|
||||
EventUtils.sendMouseEvent({ type: "mousedown" },
|
||||
document.querySelectorAll("#details-pane tab")[2]);
|
||||
|
||||
testParamsTab("urlencoded")
|
||||
.then(() => {
|
||||
RequestsMenu.selectedIndex = 1;
|
||||
return testParamsTab("multipart");
|
||||
})
|
||||
.then(() => {
|
||||
return teardown(aMonitor);
|
||||
})
|
||||
.then(finish);
|
||||
|
||||
function testParamsTab(aType) {
|
||||
let tab = document.querySelectorAll("#details-pane tab")[2];
|
||||
let tabpanel = document.querySelectorAll("#details-pane tabpanel")[2];
|
||||
|
||||
is(tab.getAttribute("selected"), "true",
|
||||
"The params tab in the network details pane should be selected.");
|
||||
|
||||
function checkVisibility(aBox) {
|
||||
is(tabpanel.querySelector("#request-params-box")
|
||||
.hasAttribute("hidden"), !aBox.contains("params"),
|
||||
"The request params box doesn't have the indended visibility.");
|
||||
|
||||
is(tabpanel.querySelector("#request-post-data-textarea-box")
|
||||
.hasAttribute("hidden"), !aBox.contains("textarea"),
|
||||
"The request post data textarea box doesn't have the indended visibility.");
|
||||
}
|
||||
|
||||
is(tabpanel.querySelectorAll(".variables-view-scope").length, 2,
|
||||
"There should be 2 param scopes displayed in this tabpanel.");
|
||||
is(tabpanel.querySelectorAll(".variables-view-empty-notice").length, 0,
|
||||
"The empty notice should not be displayed in this tabpanel.");
|
||||
|
||||
let queryScope = tabpanel.querySelectorAll(".variables-view-scope")[0];
|
||||
let postScope = tabpanel.querySelectorAll(".variables-view-scope")[1];
|
||||
|
||||
is(queryScope.querySelector(".name").getAttribute("value"),
|
||||
L10N.getStr("paramsQueryString"),
|
||||
"The query scope doesn't have the correct title.");
|
||||
|
||||
is(postScope.querySelector(".name").getAttribute("value"),
|
||||
L10N.getStr(aType == "urlencoded" ? "paramsFormData" : "paramsPostPayload"),
|
||||
"The post scope doesn't have the correct title.");
|
||||
|
||||
is(queryScope.querySelectorAll(".variables-view-variable .name")[0].getAttribute("value"),
|
||||
"foo", "The first query param name was incorrect.");
|
||||
is(queryScope.querySelectorAll(".variables-view-variable .value")[0].getAttribute("value"),
|
||||
"\"bar\"", "The first query param value was incorrect.");
|
||||
is(queryScope.querySelectorAll(".variables-view-variable .name")[1].getAttribute("value"),
|
||||
"baz", "The second query param name was incorrect.");
|
||||
is(queryScope.querySelectorAll(".variables-view-variable .value")[1].getAttribute("value"),
|
||||
"\"42\"", "The second query param value was incorrect.");
|
||||
is(queryScope.querySelectorAll(".variables-view-variable .name")[2].getAttribute("value"),
|
||||
"type", "The third query param name was incorrect.");
|
||||
is(queryScope.querySelectorAll(".variables-view-variable .value")[2].getAttribute("value"),
|
||||
"\"" + aType + "\"", "The third query param value was incorrect.");
|
||||
|
||||
if (aType == "urlencoded") {
|
||||
checkVisibility("params");
|
||||
|
||||
is(tabpanel.querySelectorAll(".variables-view-variable").length, 5,
|
||||
"There should be 6 param values displayed in this tabpanel.");
|
||||
is(queryScope.querySelectorAll(".variables-view-variable").length, 3,
|
||||
"There should be 3 param values displayed in the query scope.");
|
||||
is(postScope.querySelectorAll(".variables-view-variable").length, 2,
|
||||
"There should be 3 param values displayed in the post scope.");
|
||||
|
||||
is(postScope.querySelectorAll(".variables-view-variable .name")[0].getAttribute("value"),
|
||||
"foo", "The first post param name was incorrect.");
|
||||
is(postScope.querySelectorAll(".variables-view-variable .value")[0].getAttribute("value"),
|
||||
"\"bar\"", "The first post param value was incorrect.");
|
||||
is(postScope.querySelectorAll(".variables-view-variable .name")[1].getAttribute("value"),
|
||||
"baz", "The second post param name was incorrect.");
|
||||
is(postScope.querySelectorAll(".variables-view-variable .value")[1].getAttribute("value"),
|
||||
"\"123\"", "The second post param value was incorrect.");
|
||||
|
||||
return Promise.resolve();
|
||||
}
|
||||
else {
|
||||
checkVisibility("params textarea");
|
||||
|
||||
is(tabpanel.querySelectorAll(".variables-view-variable").length, 3,
|
||||
"There should be 3 param values displayed in this tabpanel.");
|
||||
is(queryScope.querySelectorAll(".variables-view-variable").length, 3,
|
||||
"There should be 3 param values displayed in the query scope.");
|
||||
is(postScope.querySelectorAll(".variables-view-variable").length, 0,
|
||||
"There should be 0 param values displayed in the post scope.");
|
||||
|
||||
return NetMonitorView.editor("#request-post-data-textarea").then((aEditor) => {
|
||||
ok(aEditor.getText().contains("Content-Disposition: form-data; name=\"text\""),
|
||||
"The text shown in the source editor is incorrect (1.1).");
|
||||
ok(aEditor.getText().contains("Content-Disposition: form-data; name=\"email\""),
|
||||
"The text shown in the source editor is incorrect (2.1).");
|
||||
ok(aEditor.getText().contains("Content-Disposition: form-data; name=\"range\""),
|
||||
"The text shown in the source editor is incorrect (3.1).");
|
||||
ok(aEditor.getText().contains("Content-Disposition: form-data; name=\"Custom field\""),
|
||||
"The text shown in the source editor is incorrect (4.1).");
|
||||
ok(aEditor.getText().contains("Some text..."),
|
||||
"The text shown in the source editor is incorrect (2.2).");
|
||||
ok(aEditor.getText().contains("42"),
|
||||
"The text shown in the source editor is incorrect (3.2).");
|
||||
ok(aEditor.getText().contains("Extra data"),
|
||||
"The text shown in the source editor is incorrect (4.2).");
|
||||
is(aEditor.getMode(), SourceEditor.MODES.TEXT,
|
||||
"The mode active in the source editor is incorrect.");
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
aDebuggee.performRequests();
|
||||
});
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Tests if the preferences and localization objects work correctly.
|
||||
*/
|
||||
|
||||
function test() {
|
||||
initNetMonitor(SIMPLE_URL).then(([aTab, aDebuggee, aMonitor]) => {
|
||||
info("Starting test... ");
|
||||
|
||||
ok(aMonitor.panelWin.L10N,
|
||||
"Should have a localization object available on the panel window.");
|
||||
ok(aMonitor.panelWin.Prefs,
|
||||
"Should have a preferences object available on the panel window.");
|
||||
|
||||
function testL10N() {
|
||||
let { L10N } = aMonitor.panelWin;
|
||||
|
||||
ok(L10N.stringBundle,
|
||||
"The localization object should have a string bundle available.");
|
||||
|
||||
let bundleName = "chrome://browser/locale/devtools/netmonitor.properties";
|
||||
let stringBundle = Services.strings.createBundle(bundleName);
|
||||
|
||||
is(L10N.getStr("netmonitor.label"),
|
||||
stringBundle.GetStringFromName("netmonitor.label"),
|
||||
"The getStr() method didn't return the expected string.");
|
||||
|
||||
is(L10N.getFormatStr("networkMenu.total", "foo"),
|
||||
stringBundle.formatStringFromName("networkMenu.total", ["foo"], 1),
|
||||
"The getFormatStr() method didn't return the expected string.");
|
||||
}
|
||||
|
||||
function testPrefs() {
|
||||
let { Prefs } = aMonitor.panelWin;
|
||||
|
||||
is(Prefs.root, "devtools.netmonitor",
|
||||
"The preferences object should have a correct root path.");
|
||||
|
||||
is(Prefs.networkDetailsWidth,
|
||||
Services.prefs.getIntPref("devtools.netmonitor.panes-network-details-width"),
|
||||
"Getting a pref should work correctly.");
|
||||
|
||||
let previousValue = Prefs.networkDetailsWidth;
|
||||
let bogusValue = ~~(Math.random() * 100);
|
||||
Prefs.networkDetailsWidth = bogusValue;
|
||||
is(Prefs.networkDetailsWidth,
|
||||
Services.prefs.getIntPref("devtools.netmonitor.panes-network-details-width"),
|
||||
"Getting a pref after it has been modified should work correctly.");
|
||||
is(Prefs.networkDetailsWidth, bogusValue,
|
||||
"The pref wasn't updated correctly in the preferences object.");
|
||||
|
||||
Prefs.networkDetailsWidth = previousValue;
|
||||
is(Prefs.networkDetailsWidth,
|
||||
Services.prefs.getIntPref("devtools.netmonitor.panes-network-details-width"),
|
||||
"Getting a pref after it has been modified again should work correctly.");
|
||||
is(Prefs.networkDetailsWidth, previousValue,
|
||||
"The pref wasn't updated correctly again in the preferences object.");
|
||||
}
|
||||
|
||||
testL10N();
|
||||
testPrefs();
|
||||
|
||||
teardown(aMonitor).then(finish);
|
||||
});
|
||||
}
|
|
@ -0,0 +1,130 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Tests if the prefs that should survive across tool reloads work.
|
||||
*/
|
||||
|
||||
function test() {
|
||||
initNetMonitor(SIMPLE_URL).then(([aTab, aDebuggee, aMonitor]) => {
|
||||
info("Starting test... ");
|
||||
|
||||
let prefsToCheck = {
|
||||
networkDetailsWidth: {
|
||||
newValue: ~~(Math.random() * 200 + 100),
|
||||
validate: () =>
|
||||
~~aMonitor._view._detailsPane.getAttribute("width"),
|
||||
modifyFrontend: (aValue) =>
|
||||
aMonitor._view._detailsPane.setAttribute("width", aValue)
|
||||
},
|
||||
/* add more prefs here... */
|
||||
};
|
||||
|
||||
function storeFirstPrefValues() {
|
||||
info("Caching initial pref values.");
|
||||
|
||||
for (let name in prefsToCheck) {
|
||||
let currentValue = aMonitor.panelWin.Prefs[name];
|
||||
prefsToCheck[name].firstValue = currentValue;
|
||||
}
|
||||
}
|
||||
|
||||
function validateFirstPrefValues() {
|
||||
info("Validating current pref values to the UI elements.");
|
||||
|
||||
for (let name in prefsToCheck) {
|
||||
let currentValue = aMonitor.panelWin.Prefs[name];
|
||||
let firstValue = prefsToCheck[name].firstValue;
|
||||
let validate = prefsToCheck[name].validate;
|
||||
|
||||
is(currentValue, firstValue,
|
||||
"Pref " + name + " should be equal to first value: " + firstValue);
|
||||
is(currentValue, validate(),
|
||||
"Pref " + name + " should validate: " + currentValue);
|
||||
}
|
||||
}
|
||||
|
||||
function modifyFrontend() {
|
||||
info("Modifying UI elements to the specified new values.");
|
||||
|
||||
for (let name in prefsToCheck) {
|
||||
let currentValue = aMonitor.panelWin.Prefs[name];
|
||||
let firstValue = prefsToCheck[name].firstValue;
|
||||
let newValue = prefsToCheck[name].newValue;
|
||||
let validate = prefsToCheck[name].validate;
|
||||
let modifyFrontend = prefsToCheck[name].modifyFrontend;
|
||||
|
||||
modifyFrontend(newValue);
|
||||
info("Modified UI element affecting " + name + " to: " + newValue);
|
||||
|
||||
is(currentValue, firstValue,
|
||||
"Pref " + name + " should still be equal to first value: " + firstValue);
|
||||
isnot(currentValue, newValue,
|
||||
"Pref " + name + " should't yet be equal to second value: " + newValue);
|
||||
is(newValue, validate(),
|
||||
"The UI element affecting " + name + " should validate: " + newValue);
|
||||
}
|
||||
}
|
||||
|
||||
function validateNewPrefValues() {
|
||||
info("Invalidating old pref values to the modified UI elements.");
|
||||
|
||||
for (let name in prefsToCheck) {
|
||||
let currentValue = aMonitor.panelWin.Prefs[name];
|
||||
let firstValue = prefsToCheck[name].firstValue;
|
||||
let newValue = prefsToCheck[name].newValue;
|
||||
let validate = prefsToCheck[name].validate;
|
||||
let modifyFrontend = prefsToCheck[name].modifyFrontend;
|
||||
|
||||
isnot(currentValue, firstValue,
|
||||
"Pref " + name + " should't be equal to first value: " + firstValue);
|
||||
is(currentValue, newValue,
|
||||
"Pref " + name + " should now be equal to second value: " + newValue);
|
||||
is(newValue, validate(),
|
||||
"The UI element affecting " + name + " should validate: " + newValue);
|
||||
}
|
||||
}
|
||||
|
||||
function resetFrontend() {
|
||||
info("Resetting UI elements to the cached initial pref values.");
|
||||
|
||||
for (let name in prefsToCheck) {
|
||||
let currentValue = aMonitor.panelWin.Prefs[name];
|
||||
let firstValue = prefsToCheck[name].firstValue;
|
||||
let newValue = prefsToCheck[name].newValue;
|
||||
let validate = prefsToCheck[name].validate;
|
||||
let modifyFrontend = prefsToCheck[name].modifyFrontend;
|
||||
|
||||
modifyFrontend(firstValue);
|
||||
info("Modified UI element affecting " + name + " to: " + firstValue);
|
||||
|
||||
isnot(currentValue, firstValue,
|
||||
"Pref " + name + " should't yet be equal to first value: " + firstValue);
|
||||
is(currentValue, newValue,
|
||||
"Pref " + name + " should still be equal to second value: " + newValue);
|
||||
is(firstValue, validate(),
|
||||
"The UI element affecting " + name + " should validate: " + firstValue);
|
||||
}
|
||||
}
|
||||
|
||||
storeFirstPrefValues();
|
||||
|
||||
// Validate and modify.
|
||||
validateFirstPrefValues();
|
||||
modifyFrontend();
|
||||
restartNetMonitor(aMonitor).then(([,, aNewMonitor]) => {
|
||||
aMonitor = aNewMonitor;
|
||||
|
||||
// Revalidate and reset.
|
||||
validateNewPrefValues();
|
||||
resetFrontend();
|
||||
restartNetMonitor(aMonitor).then(([,, aNewMonitor]) => {
|
||||
aMonitor = aNewMonitor;
|
||||
|
||||
// Revalidate and finish.
|
||||
validateFirstPrefValues();
|
||||
teardown(aMonitor).then(finish);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
|
@ -0,0 +1,84 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Simple check if the network monitor starts up and shuts down properly.
|
||||
*/
|
||||
|
||||
function test() {
|
||||
initNetMonitor(SIMPLE_URL).then(([aTab, aDebuggee, aMonitor]) => {
|
||||
info("Starting test... ");
|
||||
|
||||
is(aTab.linkedBrowser.contentWindow.wrappedJSObject.location, SIMPLE_URL,
|
||||
"The current tab's location is the correct one.");
|
||||
is(aDebuggee.location, SIMPLE_URL,
|
||||
"The current debuggee's location is the correct one.");
|
||||
|
||||
function checkIfInitialized(aTag) {
|
||||
info("Checking if initialization is ok (" + aTag + ").");
|
||||
|
||||
ok(aMonitor._view,
|
||||
"The network monitor view object exists (" + aTag + ").");
|
||||
ok(aMonitor._view._isInitialized,
|
||||
"The network monitor view object exists and is initialized (" + aTag + ").");
|
||||
|
||||
ok(aMonitor._controller,
|
||||
"The network monitor controller object exists (" + aTag + ").");
|
||||
ok(aMonitor._controller._isInitialized,
|
||||
"The network monitor controller object exists and is initialized (" + aTag + ").");
|
||||
|
||||
ok(aMonitor.isReady,
|
||||
"The network monitor panel appears to be ready (" + aTag + ").");
|
||||
|
||||
ok(aMonitor._controller.client,
|
||||
"There should be a client available at this point (" + aTag + ").");
|
||||
ok(aMonitor._controller.tabClient,
|
||||
"There should be a tabClient available at this point (" + aTag + ").");
|
||||
ok(aMonitor._controller.webConsoleClient,
|
||||
"There should be a webConsoleClient available at this point (" + aTag + ").");
|
||||
}
|
||||
|
||||
function checkIfDestroyed(aTag) {
|
||||
info("Checking if destruction is ok.");
|
||||
|
||||
ok(!aMonitor._controller.client,
|
||||
"There shouldn't be a client available after destruction (" + aTag + ").");
|
||||
ok(!aMonitor._controller.tabClient,
|
||||
"There shouldn't be a tabClient available after destruction (" + aTag + ").");
|
||||
ok(!aMonitor._controller.webConsoleClient,
|
||||
"There shouldn't be a webConsoleClient available after destruction (" + aTag + ").");
|
||||
}
|
||||
|
||||
executeSoon(() => {
|
||||
checkIfInitialized(1);
|
||||
|
||||
aMonitor._controller.startupNetMonitor()
|
||||
.then(() => {
|
||||
info("Starting up again shouldn't do anything special.");
|
||||
checkIfInitialized(2);
|
||||
return aMonitor._controller.connect();
|
||||
})
|
||||
.then(() => {
|
||||
info("Connecting again shouldn't do anything special.");
|
||||
checkIfInitialized(3);
|
||||
return teardown(aMonitor);
|
||||
})
|
||||
.then(finish);
|
||||
});
|
||||
|
||||
registerCleanupFunction(() => {
|
||||
checkIfDestroyed(1);
|
||||
|
||||
aMonitor._controller.shutdownNetMonitor()
|
||||
.then(() => {
|
||||
info("Shutting down again shouldn't do anything special.");
|
||||
checkIfDestroyed(2);
|
||||
return aMonitor._controller.disconnect();
|
||||
})
|
||||
.then(() => {
|
||||
info("Disconnecting again shouldn't do anything special.");
|
||||
checkIfDestroyed(3);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
|
@ -0,0 +1,232 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Tests if requests render correct information in the menu UI.
|
||||
*/
|
||||
|
||||
function test() {
|
||||
initNetMonitor(SIMPLE_SJS).then(([aTab, aDebuggee, aMonitor]) => {
|
||||
info("Starting test... ");
|
||||
|
||||
let { NetMonitorView } = aMonitor.panelWin;
|
||||
let { RequestsMenu } = NetMonitorView;
|
||||
|
||||
RequestsMenu.lazyUpdate = false;
|
||||
|
||||
waitForNetworkEvents(aMonitor, 1)
|
||||
.then(() => teardown(aMonitor))
|
||||
.then(finish);
|
||||
|
||||
aMonitor.panelWin.once("NetMonitor:NetworkEvent", () => {
|
||||
is(RequestsMenu.selectedItem, null,
|
||||
"There shouldn't be any selected item in the requests menu.");
|
||||
is(RequestsMenu.itemCount, 1,
|
||||
"The requests menu should not be empty after the first request.");
|
||||
is(NetMonitorView.detailsPaneHidden, true,
|
||||
"The details pane should still be hidden after the first request.");
|
||||
|
||||
let requestItem = RequestsMenu.getItemAtIndex(0);
|
||||
let target = requestItem.target;
|
||||
|
||||
is(typeof requestItem.attachment.id, "string",
|
||||
"The attached id is incorrect.");
|
||||
isnot(requestItem.attachment.id, "",
|
||||
"The attached id should not be empty.");
|
||||
|
||||
is(typeof requestItem.attachment.startedDeltaMillis, "number",
|
||||
"The attached startedDeltaMillis is incorrect.");
|
||||
is(requestItem.attachment.startedDeltaMillis, 0,
|
||||
"The attached startedDeltaMillis should be zero.");
|
||||
|
||||
is(typeof requestItem.attachment.startedMillis, "number",
|
||||
"The attached startedMillis is incorrect.");
|
||||
isnot(requestItem.attachment.startedMillis, 0,
|
||||
"The attached startedMillis should not be zero.");
|
||||
|
||||
is(requestItem.attachment.requestHeaders, undefined,
|
||||
"The requestHeaders should not yet be set.");
|
||||
is(requestItem.attachment.requestCookies, undefined,
|
||||
"The requestCookies should not yet be set.");
|
||||
is(requestItem.attachment.requestPostData, undefined,
|
||||
"The requestPostData should not yet be set.");
|
||||
|
||||
is(requestItem.attachment.responseHeaders, undefined,
|
||||
"The responseHeaders should not yet be set.");
|
||||
is(requestItem.attachment.responseCookies, undefined,
|
||||
"The responseCookies should not yet be set.");
|
||||
|
||||
is(requestItem.attachment.httpVersion, undefined,
|
||||
"The httpVersion should not yet be set.");
|
||||
is(requestItem.attachment.status, undefined,
|
||||
"The status should not yet be set.");
|
||||
is(requestItem.attachment.statusText, undefined,
|
||||
"The statusText should not yet be set.");
|
||||
|
||||
is(requestItem.attachment.headersSize, undefined,
|
||||
"The headersSize should not yet be set.");
|
||||
is(requestItem.attachment.contentSize, undefined,
|
||||
"The contentSize should not yet be set.");
|
||||
|
||||
is(requestItem.attachment.mimeType, undefined,
|
||||
"The mimeType should not yet be set.");
|
||||
is(requestItem.attachment.responseContent, undefined,
|
||||
"The responseContent should not yet be set.");
|
||||
|
||||
is(requestItem.attachment.totalTime, undefined,
|
||||
"The totalTime should not yet be set.");
|
||||
is(requestItem.attachment.eventTimings, undefined,
|
||||
"The eventTimings should not yet be set.");
|
||||
|
||||
verifyRequestItemTarget(requestItem, "GET", SIMPLE_SJS);
|
||||
});
|
||||
|
||||
aMonitor.panelWin.once("NetMonitor:NetworkEventUpdated:RequestHeaders", () => {
|
||||
let requestItem = RequestsMenu.getItemAtIndex(0);
|
||||
|
||||
ok(requestItem.attachment.requestHeaders,
|
||||
"There should be a requestHeaders attachment available.");
|
||||
is(requestItem.attachment.requestHeaders.headers.length, 7,
|
||||
"The requestHeaders attachment has an incorrect |headers| property.");
|
||||
isnot(requestItem.attachment.requestHeaders.headersSize, 0,
|
||||
"The requestHeaders attachment has an incorrect |headersSize| property.");
|
||||
// Can't test for the exact request headers size because the value may
|
||||
// vary across platforms ("User-Agent" header differs).
|
||||
|
||||
verifyRequestItemTarget(requestItem, "GET", SIMPLE_SJS);
|
||||
});
|
||||
|
||||
aMonitor.panelWin.once("NetMonitor:NetworkEventUpdated:RequestCookies", () => {
|
||||
let requestItem = RequestsMenu.getItemAtIndex(0);
|
||||
|
||||
ok(requestItem.attachment.requestCookies,
|
||||
"There should be a requestCookies attachment available.");
|
||||
is(requestItem.attachment.requestCookies.cookies.length, 0,
|
||||
"The requestCookies attachment has an incorrect |cookies| property.");
|
||||
|
||||
verifyRequestItemTarget(requestItem, "GET", SIMPLE_SJS);
|
||||
});
|
||||
|
||||
aMonitor.panelWin.once("NetMonitor:NetworkEventUpdated:RequestPostData", () => {
|
||||
ok(false, "Trap listener: this request doesn't have any post data.")
|
||||
});
|
||||
|
||||
aMonitor.panelWin.once("NetMonitor:NetworkEventUpdated:ResponseHeaders", () => {
|
||||
let requestItem = RequestsMenu.getItemAtIndex(0);
|
||||
|
||||
ok(requestItem.attachment.responseHeaders,
|
||||
"There should be a responseHeaders attachment available.");
|
||||
is(requestItem.attachment.responseHeaders.headers.length, 6,
|
||||
"The responseHeaders attachment has an incorrect |headers| property.");
|
||||
is(requestItem.attachment.responseHeaders.headersSize, 173,
|
||||
"The responseHeaders attachment has an incorrect |headersSize| property.");
|
||||
|
||||
verifyRequestItemTarget(requestItem, "GET", SIMPLE_SJS);
|
||||
});
|
||||
|
||||
aMonitor.panelWin.once("NetMonitor:NetworkEventUpdated:ResponseCookies", () => {
|
||||
let requestItem = RequestsMenu.getItemAtIndex(0);
|
||||
|
||||
ok(requestItem.attachment.responseCookies,
|
||||
"There should be a responseCookies attachment available.");
|
||||
is(requestItem.attachment.responseCookies.cookies.length, 0,
|
||||
"The responseCookies attachment has an incorrect |cookies| property.");
|
||||
|
||||
verifyRequestItemTarget(requestItem, "GET", SIMPLE_SJS);
|
||||
});
|
||||
|
||||
aMonitor.panelWin.once("NetMonitor:NetworkEventUpdating:ResponseStart", () => {
|
||||
let requestItem = RequestsMenu.getItemAtIndex(0);
|
||||
|
||||
is(requestItem.attachment.httpVersion, "HTTP/1.1",
|
||||
"The httpVersion attachment has an incorrect value.");
|
||||
is(requestItem.attachment.status, "200",
|
||||
"The status attachment has an incorrect value.");
|
||||
is(requestItem.attachment.statusText, "Och Aye",
|
||||
"The statusText attachment has an incorrect value.");
|
||||
is(requestItem.attachment.headersSize, 173,
|
||||
"The headersSize attachment has an incorrect value.");
|
||||
|
||||
verifyRequestItemTarget(requestItem, "GET", SIMPLE_SJS, {
|
||||
status: "200"
|
||||
});
|
||||
});
|
||||
|
||||
aMonitor.panelWin.once("NetMonitor:NetworkEventUpdating:ResponseContent", () => {
|
||||
let requestItem = RequestsMenu.getItemAtIndex(0);
|
||||
|
||||
is(requestItem.attachment.contentSize, "12",
|
||||
"The contentSize attachment has an incorrect value.");
|
||||
is(requestItem.attachment.mimeType, "text/plain; charset=utf-8",
|
||||
"The mimeType attachment has an incorrect value.");
|
||||
|
||||
verifyRequestItemTarget(requestItem, "GET", SIMPLE_SJS, {
|
||||
type: "plain",
|
||||
size: "0.01kb"
|
||||
});
|
||||
});
|
||||
|
||||
aMonitor.panelWin.once("NetMonitor:NetworkEventUpdated:ResponseContent", () => {
|
||||
let requestItem = RequestsMenu.getItemAtIndex(0);
|
||||
|
||||
ok(requestItem.attachment.responseContent,
|
||||
"There should be a responseContent attachment available.");
|
||||
is(requestItem.attachment.responseContent.content.mimeType, "text/plain; charset=utf-8",
|
||||
"The responseContent attachment has an incorrect |content.mimeType| property.");
|
||||
is(requestItem.attachment.responseContent.content.text, "Hello world!",
|
||||
"The responseContent attachment has an incorrect |content.text| property.");
|
||||
is(requestItem.attachment.responseContent.content.size, 12,
|
||||
"The responseContent attachment has an incorrect |content.size| property.");
|
||||
|
||||
verifyRequestItemTarget(requestItem, "GET", SIMPLE_SJS, {
|
||||
type: "plain",
|
||||
size: "0.01kb"
|
||||
});
|
||||
});
|
||||
|
||||
aMonitor.panelWin.once("NetMonitor:NetworkEventUpdating:EventTimings", () => {
|
||||
let requestItem = RequestsMenu.getItemAtIndex(0);
|
||||
|
||||
is(typeof requestItem.attachment.totalTime, "number",
|
||||
"The attached totalTime is incorrect.");
|
||||
ok(requestItem.attachment.totalTime >= 0,
|
||||
"The attached totalTime should be positive.");
|
||||
|
||||
is(typeof requestItem.attachment.endedMillis, "number",
|
||||
"The attached endedMillis is incorrect.");
|
||||
ok(requestItem.attachment.endedMillis >= 0,
|
||||
"The attached endedMillis should be positive.");
|
||||
|
||||
verifyRequestItemTarget(requestItem, "GET", SIMPLE_SJS, {
|
||||
time: true
|
||||
});
|
||||
});
|
||||
|
||||
aMonitor.panelWin.once("NetMonitor:NetworkEventUpdated:EventTimings", () => {
|
||||
let requestItem = RequestsMenu.getItemAtIndex(0);
|
||||
|
||||
ok(requestItem.attachment.eventTimings,
|
||||
"There should be a eventTimings attachment available.");
|
||||
is(typeof requestItem.attachment.eventTimings.timings.blocked, "number",
|
||||
"The eventTimings attachment has an incorrect |timings.blocked| property.");
|
||||
is(typeof requestItem.attachment.eventTimings.timings.dns, "number",
|
||||
"The eventTimings attachment has an incorrect |timings.dns| property.");
|
||||
is(typeof requestItem.attachment.eventTimings.timings.connect, "number",
|
||||
"The eventTimings attachment has an incorrect |timings.connect| property.");
|
||||
is(typeof requestItem.attachment.eventTimings.timings.send, "number",
|
||||
"The eventTimings attachment has an incorrect |timings.send| property.");
|
||||
is(typeof requestItem.attachment.eventTimings.timings.wait, "number",
|
||||
"The eventTimings attachment has an incorrect |timings.wait| property.");
|
||||
is(typeof requestItem.attachment.eventTimings.timings.receive, "number",
|
||||
"The eventTimings attachment has an incorrect |timings.receive| property.");
|
||||
is(typeof requestItem.attachment.eventTimings.totalTime, "number",
|
||||
"The eventTimings attachment has an incorrect |totalTime| property.");
|
||||
|
||||
verifyRequestItemTarget(requestItem, "GET", SIMPLE_SJS, {
|
||||
time: true
|
||||
});
|
||||
});
|
||||
|
||||
aDebuggee.location.reload();
|
||||
});
|
||||
}
|
|
@ -0,0 +1,225 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Tests if requests render correct information in the details UI.
|
||||
*/
|
||||
|
||||
function test() {
|
||||
initNetMonitor(SIMPLE_SJS).then(([aTab, aDebuggee, aMonitor]) => {
|
||||
info("Starting test... ");
|
||||
|
||||
let { document, L10N, SourceEditor, NetMonitorView } = aMonitor.panelWin;
|
||||
let { RequestsMenu, NetworkDetails } = NetMonitorView;
|
||||
|
||||
RequestsMenu.lazyUpdate = false;
|
||||
|
||||
waitForNetworkEvents(aMonitor, 1).then(() => {
|
||||
is(RequestsMenu.selectedItem, null,
|
||||
"There shouldn't be any selected item in the requests menu.");
|
||||
is(RequestsMenu.itemCount, 1,
|
||||
"The requests menu should not be empty after the first request.");
|
||||
is(NetMonitorView.detailsPaneHidden, true,
|
||||
"The details pane should still be hidden after the first request.");
|
||||
|
||||
EventUtils.sendMouseEvent({ type: "mousedown" },
|
||||
document.getElementById("details-pane-toggle"));
|
||||
|
||||
isnot(RequestsMenu.selectedItem, null,
|
||||
"There should be a selected item in the requests menu.");
|
||||
is(RequestsMenu.selectedIndex, 0,
|
||||
"The first item should be selected in the requests menu.");
|
||||
is(NetMonitorView.detailsPaneHidden, false,
|
||||
"The details pane should not be hidden after toggle button was pressed.");
|
||||
|
||||
testHeadersTab();
|
||||
testCookiesTab();
|
||||
testParamsTab();
|
||||
testResponseTab()
|
||||
.then(() => {
|
||||
testTimingsTab();
|
||||
return teardown(aMonitor);
|
||||
})
|
||||
.then(finish);
|
||||
});
|
||||
|
||||
function testHeadersTab() {
|
||||
let tab = document.querySelectorAll("#details-pane tab")[0];
|
||||
let tabpanel = document.querySelectorAll("#details-pane tabpanel")[0];
|
||||
|
||||
is(tab.getAttribute("selected"), "true",
|
||||
"The headers tab in the network details pane should be selected.");
|
||||
|
||||
is(tabpanel.querySelector("#headers-summary-url-value").getAttribute("value"),
|
||||
SIMPLE_SJS, "The url summary value is incorrect.");
|
||||
is(tabpanel.querySelector("#headers-summary-method-value").getAttribute("value"),
|
||||
"GET", "The method summary value is incorrect.");
|
||||
is(tabpanel.querySelector("#headers-summary-status-circle").getAttribute("code"),
|
||||
"200", "The status summary code is incorrect.");
|
||||
is(tabpanel.querySelector("#headers-summary-status-value").getAttribute("value"),
|
||||
"200 Och Aye", "The status summary value is incorrect.");
|
||||
|
||||
is(tabpanel.querySelectorAll(".variables-view-scope").length, 2,
|
||||
"There should be 2 header scopes displayed in this tabpanel.");
|
||||
is(tabpanel.querySelectorAll(".variable-or-property").length, 13,
|
||||
"There should be 13 header values displayed in this tabpanel.");
|
||||
is(tabpanel.querySelectorAll(".variables-view-empty-notice").length, 0,
|
||||
"The empty notice should not be displayed in this tabpanel.");
|
||||
|
||||
let responseScope = tabpanel.querySelectorAll(".variables-view-scope")[0];
|
||||
let requestScope = tabpanel.querySelectorAll(".variables-view-scope")[1];
|
||||
|
||||
is(responseScope.querySelector(".name").getAttribute("value"),
|
||||
L10N.getStr("responseHeaders") + " (" +
|
||||
L10N.getFormatStr("networkMenu.size", "0.169") + ")",
|
||||
"The response headers scope doesn't have the correct title.");
|
||||
|
||||
ok(requestScope.querySelector(".name").getAttribute("value").contains(
|
||||
L10N.getStr("requestHeaders") + " (0."),
|
||||
// Can't test for full request headers title because the size may
|
||||
// vary across platforms ("User-Agent" header differs).
|
||||
"The request headers scope doesn't have the correct title.");
|
||||
|
||||
is(responseScope.querySelectorAll(".variables-view-variable .name")[0].getAttribute("value"),
|
||||
"Connection", "The first response header name was incorrect.");
|
||||
is(responseScope.querySelectorAll(".variables-view-variable .value")[0].getAttribute("value"),
|
||||
"\"close\"", "The first response header value was incorrect.");
|
||||
is(responseScope.querySelectorAll(".variables-view-variable .name")[1].getAttribute("value"),
|
||||
"Content-Length", "The second response header name was incorrect.");
|
||||
is(responseScope.querySelectorAll(".variables-view-variable .value")[1].getAttribute("value"),
|
||||
"\"12\"", "The second response header value was incorrect.");
|
||||
is(responseScope.querySelectorAll(".variables-view-variable .name")[2].getAttribute("value"),
|
||||
"Content-Type", "The third response header name was incorrect.");
|
||||
is(responseScope.querySelectorAll(".variables-view-variable .value")[2].getAttribute("value"),
|
||||
"\"text/plain; charset=utf-8\"", "The third response header value was incorrect.");
|
||||
is(responseScope.querySelectorAll(".variables-view-variable .name")[5].getAttribute("value"),
|
||||
"foo-bar", "The last response header name was incorrect.");
|
||||
is(responseScope.querySelectorAll(".variables-view-variable .value")[5].getAttribute("value"),
|
||||
"\"baz\"", "The last response header value was incorrect.");
|
||||
|
||||
is(requestScope.querySelectorAll(".variables-view-variable .name")[0].getAttribute("value"),
|
||||
"Host", "The first request header name was incorrect.");
|
||||
is(requestScope.querySelectorAll(".variables-view-variable .value")[0].getAttribute("value"),
|
||||
"\"example.com\"", "The first request header value was incorrect.");
|
||||
is(requestScope.querySelectorAll(".variables-view-variable .name")[5].getAttribute("value"),
|
||||
"Connection", "The penultimate request header name was incorrect.");
|
||||
is(requestScope.querySelectorAll(".variables-view-variable .value")[5].getAttribute("value"),
|
||||
"\"keep-alive\"", "The penultimate request header value was incorrect.");
|
||||
is(requestScope.querySelectorAll(".variables-view-variable .name")[6].getAttribute("value"),
|
||||
"Cache-Control", "The last request header name was incorrect.");
|
||||
is(requestScope.querySelectorAll(".variables-view-variable .value")[6].getAttribute("value"),
|
||||
"\"max-age=0\"", "The last request header value was incorrect.");
|
||||
}
|
||||
|
||||
function testCookiesTab() {
|
||||
EventUtils.sendMouseEvent({ type: "mousedown" },
|
||||
document.querySelectorAll("#details-pane tab")[1]);
|
||||
|
||||
let tab = document.querySelectorAll("#details-pane tab")[1];
|
||||
let tabpanel = document.querySelectorAll("#details-pane tabpanel")[1];
|
||||
|
||||
is(tab.getAttribute("selected"), "true",
|
||||
"The cookies tab in the network details pane should be selected.");
|
||||
|
||||
is(tabpanel.querySelectorAll(".variables-view-scope").length, 0,
|
||||
"There should be no cookie scopes displayed in this tabpanel.");
|
||||
is(tabpanel.querySelectorAll(".variable-or-property").length, 0,
|
||||
"There should be no cookie values displayed in this tabpanel.");
|
||||
is(tabpanel.querySelectorAll(".variables-view-empty-notice").length, 1,
|
||||
"The empty notice should be displayed in this tabpanel.");
|
||||
}
|
||||
|
||||
function testParamsTab() {
|
||||
EventUtils.sendMouseEvent({ type: "mousedown" },
|
||||
document.querySelectorAll("#details-pane tab")[2]);
|
||||
|
||||
let tab = document.querySelectorAll("#details-pane tab")[2];
|
||||
let tabpanel = document.querySelectorAll("#details-pane tabpanel")[2];
|
||||
|
||||
is(tab.getAttribute("selected"), "true",
|
||||
"The params tab in the network details pane should be selected.");
|
||||
|
||||
is(tabpanel.querySelectorAll(".variables-view-scope").length, 0,
|
||||
"There should be no param scopes displayed in this tabpanel.");
|
||||
is(tabpanel.querySelectorAll(".variable-or-property").length, 0,
|
||||
"There should be no param values displayed in this tabpanel.");
|
||||
is(tabpanel.querySelectorAll(".variables-view-empty-notice").length, 1,
|
||||
"The empty notice should be displayed in this tabpanel.");
|
||||
|
||||
is(tabpanel.querySelector("#request-params-box")
|
||||
.hasAttribute("hidden"), false,
|
||||
"The request params box should not be hidden.");
|
||||
|
||||
is(tabpanel.querySelector("#request-post-data-textarea-box")
|
||||
.hasAttribute("hidden"), true,
|
||||
"The request post data textarea box should be hidden.");
|
||||
}
|
||||
|
||||
function testResponseTab() {
|
||||
EventUtils.sendMouseEvent({ type: "mousedown" },
|
||||
document.querySelectorAll("#details-pane tab")[3]);
|
||||
|
||||
let tab = document.querySelectorAll("#details-pane tab")[3];
|
||||
let tabpanel = document.querySelectorAll("#details-pane tabpanel")[3];
|
||||
|
||||
is(tab.getAttribute("selected"), "true",
|
||||
"The response tab in the network details pane should be selected.");
|
||||
|
||||
is(tabpanel.querySelector("#response-content-json-box")
|
||||
.hasAttribute("hidden"), true,
|
||||
"The response content json box should be hidden.");
|
||||
|
||||
is(tabpanel.querySelector("#response-content-textarea-box")
|
||||
.hasAttribute("hidden"), false,
|
||||
"The response content textarea box should not be hidden.");
|
||||
|
||||
is(tabpanel.querySelector("#response-content-image-box")
|
||||
.hasAttribute("hidden"), true,
|
||||
"The response content image box should be hidden.");
|
||||
|
||||
return NetMonitorView.editor("#response-content-textarea").then((aEditor) => {
|
||||
is(aEditor.getText(), "Hello world!",
|
||||
"The text shown in the source editor is incorrect.");
|
||||
is(aEditor.getMode(), SourceEditor.MODES.TEXT,
|
||||
"The mode active in the source editor is incorrect.");
|
||||
});
|
||||
}
|
||||
|
||||
function testTimingsTab() {
|
||||
EventUtils.sendMouseEvent({ type: "mousedown" },
|
||||
document.querySelectorAll("#details-pane tab")[4]);
|
||||
|
||||
let tab = document.querySelectorAll("#details-pane tab")[4];
|
||||
let tabpanel = document.querySelectorAll("#details-pane tabpanel")[4];
|
||||
|
||||
is(tab.getAttribute("selected"), "true",
|
||||
"The timings tab in the network details pane should be selected.");
|
||||
|
||||
ok(tabpanel.querySelector("#timings-summary-blocked .requests-menu-timings-total")
|
||||
.getAttribute("value").match(/[0-9]+ms$/),
|
||||
"The blocked timing info does not appear to be correct.");
|
||||
|
||||
ok(tabpanel.querySelector("#timings-summary-dns .requests-menu-timings-total")
|
||||
.getAttribute("value").match(/[0-9]+ms$/),
|
||||
"The dns timing info does not appear to be correct.");
|
||||
|
||||
ok(tabpanel.querySelector("#timings-summary-connect .requests-menu-timings-total")
|
||||
.getAttribute("value").match(/[0-9]+ms$/),
|
||||
"The connect timing info does not appear to be correct.");
|
||||
|
||||
ok(tabpanel.querySelector("#timings-summary-send .requests-menu-timings-total")
|
||||
.getAttribute("value").match(/[0-9]+ms$/),
|
||||
"The send timing info does not appear to be correct.");
|
||||
|
||||
ok(tabpanel.querySelector("#timings-summary-wait .requests-menu-timings-total")
|
||||
.getAttribute("value").match(/[0-9]+ms$/),
|
||||
"The wait timing info does not appear to be correct.");
|
||||
|
||||
ok(tabpanel.querySelector("#timings-summary-receive .requests-menu-timings-total")
|
||||
.getAttribute("value").match(/[0-9]+ms$/),
|
||||
"The receive timing info does not appear to be correct.");
|
||||
}
|
||||
|
||||
aDebuggee.location.reload();
|
||||
});
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Tests if requests are handled correctly.
|
||||
*/
|
||||
|
||||
function test() {
|
||||
initNetMonitor(SIMPLE_URL).then(([aTab, aDebuggee, aMonitor]) => {
|
||||
info("Starting test... ");
|
||||
|
||||
let { document, NetMonitorView } = aMonitor.panelWin;
|
||||
let { RequestsMenu } = NetMonitorView;
|
||||
|
||||
RequestsMenu.lazyUpdate = false;
|
||||
|
||||
is(document.querySelector(".requests-menu-empty-notice")
|
||||
.hasAttribute("hidden"), false,
|
||||
"An empty notice should be displayed when the frontend is opened.");
|
||||
is(RequestsMenu.itemCount, 0,
|
||||
"The requests menu should be empty when the frontend is opened.");
|
||||
is(NetMonitorView.detailsPaneHidden, true,
|
||||
"The details pane should be hidden when the frontend is opened.");
|
||||
|
||||
aMonitor.panelWin.once("NetMonitor:NetworkEvent", () => {
|
||||
is(document.querySelector(".requests-menu-empty-notice")
|
||||
.hasAttribute("hidden"), true,
|
||||
"The empty notice should be hidden after the first request.");
|
||||
is(RequestsMenu.itemCount, 1,
|
||||
"The requests menu should not be empty after the first request.");
|
||||
is(NetMonitorView.detailsPaneHidden, true,
|
||||
"The details pane should still be hidden after the first request.");
|
||||
|
||||
aMonitor.panelWin.once("NetMonitor:NetworkEvent", () => {
|
||||
is(document.querySelector(".requests-menu-empty-notice")
|
||||
.hasAttribute("hidden"), true,
|
||||
"The empty notice should be still hidden after a reload.");
|
||||
is(RequestsMenu.itemCount, 1,
|
||||
"The requests menu should not be empty after a reload.");
|
||||
is(NetMonitorView.detailsPaneHidden, true,
|
||||
"The details pane should still be hidden after a reload.");
|
||||
|
||||
teardown(aMonitor).then(finish);
|
||||
});
|
||||
|
||||
aDebuggee.location.reload();
|
||||
});
|
||||
|
||||
aDebuggee.location.reload();
|
||||
});
|
||||
}
|
|
@ -0,0 +1,146 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Tests if requests display the correct status code and text in the UI.
|
||||
*/
|
||||
|
||||
function test() {
|
||||
initNetMonitor(STATUS_CODES_URL).then(([aTab, aDebuggee, aMonitor]) => {
|
||||
info("Starting test... ");
|
||||
|
||||
let { document, L10N, NetMonitorView } = aMonitor.panelWin;
|
||||
let { RequestsMenu, NetworkDetails } = NetMonitorView;
|
||||
|
||||
RequestsMenu.lazyUpdate = false;
|
||||
NetworkDetails._params.lazyEmpty = false;
|
||||
|
||||
waitForNetworkEvents(aMonitor, 5).then(() => {
|
||||
let requestItems = [];
|
||||
|
||||
verifyRequestItemTarget(requestItems[0] = RequestsMenu.getItemAtIndex(0),
|
||||
"GET", STATUS_CODES_SJS + "?sts=100", {
|
||||
status: 101,
|
||||
type: "plain",
|
||||
size: "0.00kb",
|
||||
time: true
|
||||
});
|
||||
verifyRequestItemTarget(requestItems[1] = RequestsMenu.getItemAtIndex(1),
|
||||
"GET", STATUS_CODES_SJS + "?sts=200", {
|
||||
status: 202,
|
||||
type: "plain",
|
||||
size: "0.02kb",
|
||||
time: true
|
||||
});
|
||||
verifyRequestItemTarget(requestItems[2] = RequestsMenu.getItemAtIndex(2),
|
||||
"GET", STATUS_CODES_SJS + "?sts=300", {
|
||||
status: 303,
|
||||
type: "plain",
|
||||
size: "0.00kb",
|
||||
time: true
|
||||
});
|
||||
verifyRequestItemTarget(requestItems[3] = RequestsMenu.getItemAtIndex(3),
|
||||
"GET", STATUS_CODES_SJS + "?sts=400", {
|
||||
status: 404,
|
||||
type: "plain",
|
||||
size: "0.02kb",
|
||||
time: true
|
||||
});
|
||||
verifyRequestItemTarget(requestItems[4] = RequestsMenu.getItemAtIndex(4),
|
||||
"GET", STATUS_CODES_SJS + "?sts=500", {
|
||||
status: 501,
|
||||
type: "plain",
|
||||
size: "0.02kb",
|
||||
time: true
|
||||
});
|
||||
|
||||
// Test summaries...
|
||||
EventUtils.sendMouseEvent({ type: "mousedown" },
|
||||
document.querySelectorAll("#details-pane tab")[0]);
|
||||
|
||||
EventUtils.sendMouseEvent({ type: "mousedown" }, requestItems[0].target);
|
||||
testSummary("GET", STATUS_CODES_SJS + "?sts=100", "101", "Switching Protocols");
|
||||
|
||||
EventUtils.sendMouseEvent({ type: "mousedown" }, requestItems[1].target);
|
||||
testSummary("GET", STATUS_CODES_SJS + "?sts=200", "202", "Created");
|
||||
|
||||
EventUtils.sendMouseEvent({ type: "mousedown" }, requestItems[2].target);
|
||||
testSummary("GET", STATUS_CODES_SJS + "?sts=300", "303", "See Other");
|
||||
|
||||
EventUtils.sendMouseEvent({ type: "mousedown" }, requestItems[3].target);
|
||||
testSummary("GET", STATUS_CODES_SJS + "?sts=400", "404", "Not Found");
|
||||
|
||||
EventUtils.sendMouseEvent({ type: "mousedown" }, requestItems[4].target);
|
||||
testSummary("GET", STATUS_CODES_SJS + "?sts=500", "501", "Not Implemented");
|
||||
|
||||
// Test params...
|
||||
EventUtils.sendMouseEvent({ type: "mousedown" },
|
||||
document.querySelectorAll("#details-pane tab")[2]);
|
||||
|
||||
EventUtils.sendMouseEvent({ type: "mousedown" }, requestItems[0].target);
|
||||
testParamsTab("\"100\"");
|
||||
|
||||
EventUtils.sendMouseEvent({ type: "mousedown" }, requestItems[1].target);
|
||||
testParamsTab("\"200\"");
|
||||
|
||||
EventUtils.sendMouseEvent({ type: "mousedown" }, requestItems[2].target);
|
||||
testParamsTab("\"300\"");
|
||||
|
||||
EventUtils.sendMouseEvent({ type: "mousedown" }, requestItems[3].target);
|
||||
testParamsTab("\"400\"");
|
||||
|
||||
EventUtils.sendMouseEvent({ type: "mousedown" }, requestItems[4].target);
|
||||
testParamsTab("\"500\"");
|
||||
|
||||
// We're done here.
|
||||
teardown(aMonitor).then(finish);
|
||||
|
||||
function testSummary(aMethod, aUrl, aStatus, aStatusText) {
|
||||
let tab = document.querySelectorAll("#details-pane tab")[0];
|
||||
let tabpanel = document.querySelectorAll("#details-pane tabpanel")[0];
|
||||
|
||||
is(tabpanel.querySelector("#headers-summary-url-value").getAttribute("value"),
|
||||
aUrl, "The url summary value is incorrect.");
|
||||
is(tabpanel.querySelector("#headers-summary-method-value").getAttribute("value"),
|
||||
aMethod, "The method summary value is incorrect.");
|
||||
is(tabpanel.querySelector("#headers-summary-status-circle").getAttribute("code"),
|
||||
aStatus, "The status summary code is incorrect.");
|
||||
is(tabpanel.querySelector("#headers-summary-status-value").getAttribute("value"),
|
||||
aStatus + " " + aStatusText, "The status summary value is incorrect.");
|
||||
}
|
||||
|
||||
function testParamsTab(aStatusParamValue) {
|
||||
let tab = document.querySelectorAll("#details-pane tab")[2];
|
||||
let tabpanel = document.querySelectorAll("#details-pane tabpanel")[2];
|
||||
|
||||
is(tabpanel.querySelectorAll(".variables-view-scope").length, 1,
|
||||
"There should be 1 param scope displayed in this tabpanel.");
|
||||
is(tabpanel.querySelectorAll(".variable-or-property").length, 1,
|
||||
"There should be 1 param value displayed in this tabpanel.");
|
||||
is(tabpanel.querySelectorAll(".variables-view-empty-notice").length, 0,
|
||||
"The empty notice should not be displayed in this tabpanel.");
|
||||
|
||||
let paramsScope = tabpanel.querySelectorAll(".variables-view-scope")[0];
|
||||
|
||||
is(paramsScope.querySelector(".name").getAttribute("value"),
|
||||
L10N.getStr("paramsQueryString"),
|
||||
"The params scope doesn't have the correct title.");
|
||||
|
||||
is(paramsScope.querySelectorAll(".variables-view-variable .name")[0].getAttribute("value"),
|
||||
"sts", "The param name was incorrect.");
|
||||
is(paramsScope.querySelectorAll(".variables-view-variable .value")[0].getAttribute("value"),
|
||||
aStatusParamValue, "The param value was incorrect.");
|
||||
|
||||
is(tabpanel.querySelector("#request-params-box")
|
||||
.hasAttribute("hidden"), false,
|
||||
"The request params box should not be hidden.");
|
||||
|
||||
is(tabpanel.querySelector("#request-post-data-textarea-box")
|
||||
.hasAttribute("hidden"), true,
|
||||
"The request post data textarea box should be hidden.");
|
||||
}
|
||||
});
|
||||
|
||||
aDebuggee.performRequests();
|
||||
});
|
||||
}
|
|
@ -0,0 +1,224 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
"use strict";
|
||||
|
||||
const { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
|
||||
|
||||
let { Services } = Cu.import("resource://gre/modules/Services.jsm", {});
|
||||
let { Promise } = Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js", {});
|
||||
let { TargetFactory } = Cu.import("resource:///modules/devtools/Target.jsm", {});
|
||||
let { gDevTools } = Cu.import("resource:///modules/devtools/gDevTools.jsm", {});
|
||||
|
||||
const EXAMPLE_URL = "http://example.com/browser/browser/devtools/netmonitor/test/";
|
||||
|
||||
const SIMPLE_URL = EXAMPLE_URL + "html_simple-test-page.html";
|
||||
const NAVIGATE_URL = EXAMPLE_URL + "html_navigate-test-page.html";
|
||||
const CONTENT_TYPE_URL = EXAMPLE_URL + "html_content-type-test-page.html";
|
||||
const STATUS_CODES_URL = EXAMPLE_URL + "html_status-codes-test-page.html";
|
||||
const POST_DATA_URL = EXAMPLE_URL + "html_post-data-test-page.html";
|
||||
|
||||
const SIMPLE_SJS = EXAMPLE_URL + "sjs_simple-test-server.sjs";
|
||||
const CONTENT_TYPE_SJS = EXAMPLE_URL + "sjs_content-type-test-server.sjs";
|
||||
const STATUS_CODES_SJS = EXAMPLE_URL + "sjs_status-codes-test-server.sjs";
|
||||
|
||||
const TEST_IMAGE = EXAMPLE_URL + "test-image.png";
|
||||
|
||||
// All tests are asynchronous.
|
||||
waitForExplicitFinish();
|
||||
|
||||
// Enable logging for all the relevant tests.
|
||||
let gEnableLogging = Services.prefs.getBoolPref("devtools.debugger.log");
|
||||
Services.prefs.setBoolPref("devtools.debugger.log", true);
|
||||
|
||||
registerCleanupFunction(() => {
|
||||
info("finish() was called, cleaning up...");
|
||||
Services.prefs.setBoolPref("devtools.debugger.log", gEnableLogging);
|
||||
});
|
||||
|
||||
function addTab(aUrl, aWindow) {
|
||||
info("Adding tab: " + aUrl);
|
||||
|
||||
let deferred = Promise.defer();
|
||||
let targetWindow = aWindow || window;
|
||||
let targetBrowser = targetWindow.gBrowser;
|
||||
|
||||
targetWindow.focus();
|
||||
let tab = targetBrowser.selectedTab = targetBrowser.addTab(aUrl);
|
||||
|
||||
tab.addEventListener("load", function onLoad() {
|
||||
tab.removeEventListener("load", onLoad, true);
|
||||
deferred.resolve(tab);
|
||||
}, true);
|
||||
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
function removeTab(aTab, aWindow) {
|
||||
info("Removing tab.");
|
||||
|
||||
let targetWindow = aWindow || window;
|
||||
let targetBrowser = targetWindow.gBrowser;
|
||||
|
||||
targetBrowser.removeTab(aTab);
|
||||
}
|
||||
|
||||
function initNetMonitor(aUrl, aWindow) {
|
||||
info("Initializing a network monitor pane.");
|
||||
|
||||
return addTab(aUrl).then((aTab) => {
|
||||
info("Net tab added successfully: " + aUrl);
|
||||
|
||||
let deferred = Promise.defer();
|
||||
let debuggee = aTab.linkedBrowser.contentWindow.wrappedJSObject;
|
||||
let target = TargetFactory.forTab(aTab);
|
||||
|
||||
gDevTools.showToolbox(target, "netmonitor").then((aToolbox) => {
|
||||
info("Netork monitor pane shown successfully.");
|
||||
|
||||
let monitor = aToolbox.getCurrentPanel();
|
||||
deferred.resolve([aTab, debuggee, monitor]);
|
||||
});
|
||||
|
||||
return deferred.promise;
|
||||
});
|
||||
}
|
||||
|
||||
function restartNetMonitor(aMonitor, aNewUrl) {
|
||||
info("Restarting the specified network monitor.");
|
||||
|
||||
let deferred = Promise.defer();
|
||||
let tab = aMonitor.target.tab;
|
||||
let url = aNewUrl || tab.linkedBrowser.contentWindow.wrappedJSObject.location.href;
|
||||
|
||||
aMonitor.once("destroyed", () => initNetMonitor(url).then(deferred.resolve));
|
||||
removeTab(tab);
|
||||
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
function teardown(aMonitor) {
|
||||
info("Destroying the specified network monitor.");
|
||||
|
||||
let deferred = Promise.defer();
|
||||
let tab = aMonitor.target.tab;
|
||||
|
||||
aMonitor.once("destroyed", deferred.resolve);
|
||||
removeTab(tab);
|
||||
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
function waitForNetworkEvents(aMonitor, aGetRequests, aPostRequests = 0) {
|
||||
let deferred = Promise.defer();
|
||||
|
||||
let panel = aMonitor.panelWin;
|
||||
let genericEvents = 0;
|
||||
let postEvents = 0;
|
||||
|
||||
function onGenericEvent() {
|
||||
genericEvents++;
|
||||
maybeResolve();
|
||||
}
|
||||
|
||||
function onPostEvent() {
|
||||
postEvents++;
|
||||
maybeResolve();
|
||||
}
|
||||
|
||||
function maybeResolve() {
|
||||
info("> Network events progress: " +
|
||||
genericEvents + "/" + ((aGetRequests + aPostRequests) * 13) + ", " +
|
||||
postEvents + "/" + (aPostRequests * 2));
|
||||
|
||||
// There are 15 updates which need to be fired for a request to be
|
||||
// considered finished. RequestPostData isn't fired for non-POST requests.
|
||||
if (genericEvents == (aGetRequests + aPostRequests) * 13 &&
|
||||
postEvents == aPostRequests * 2) {
|
||||
|
||||
panel.off("NetMonitor:NetworkEventUpdating:RequestHeaders", onGenericEvent);
|
||||
panel.off("NetMonitor:NetworkEventUpdated:RequestHeaders", onGenericEvent);
|
||||
panel.off("NetMonitor:NetworkEventUpdating:RequestCookies", onGenericEvent);
|
||||
panel.off("NetMonitor:NetworkEventUpdating:RequestPostData", onPostEvent);
|
||||
panel.off("NetMonitor:NetworkEventUpdated:RequestPostData", onPostEvent);
|
||||
panel.off("NetMonitor:NetworkEventUpdated:RequestCookies", onGenericEvent);
|
||||
panel.off("NetMonitor:NetworkEventUpdating:ResponseHeaders", onGenericEvent);
|
||||
panel.off("NetMonitor:NetworkEventUpdated:ResponseHeaders", onGenericEvent);
|
||||
panel.off("NetMonitor:NetworkEventUpdating:ResponseCookies", onGenericEvent);
|
||||
panel.off("NetMonitor:NetworkEventUpdated:ResponseCookies", onGenericEvent);
|
||||
panel.off("NetMonitor:NetworkEventUpdating:ResponseStart", onGenericEvent);
|
||||
panel.off("NetMonitor:NetworkEventUpdating:ResponseContent", onGenericEvent);
|
||||
panel.off("NetMonitor:NetworkEventUpdated:ResponseContent", onGenericEvent);
|
||||
panel.off("NetMonitor:NetworkEventUpdating:EventTimings", onGenericEvent);
|
||||
panel.off("NetMonitor:NetworkEventUpdated:EventTimings", onGenericEvent);
|
||||
|
||||
executeSoon(deferred.resolve);
|
||||
}
|
||||
}
|
||||
|
||||
panel.on("NetMonitor:NetworkEventUpdating:RequestHeaders", onGenericEvent);
|
||||
panel.on("NetMonitor:NetworkEventUpdated:RequestHeaders", onGenericEvent);
|
||||
panel.on("NetMonitor:NetworkEventUpdating:RequestCookies", onGenericEvent);
|
||||
panel.on("NetMonitor:NetworkEventUpdating:RequestPostData", onPostEvent);
|
||||
panel.on("NetMonitor:NetworkEventUpdated:RequestPostData", onPostEvent);
|
||||
panel.on("NetMonitor:NetworkEventUpdated:RequestCookies", onGenericEvent);
|
||||
panel.on("NetMonitor:NetworkEventUpdating:ResponseHeaders", onGenericEvent);
|
||||
panel.on("NetMonitor:NetworkEventUpdated:ResponseHeaders", onGenericEvent);
|
||||
panel.on("NetMonitor:NetworkEventUpdating:ResponseCookies", onGenericEvent);
|
||||
panel.on("NetMonitor:NetworkEventUpdated:ResponseCookies", onGenericEvent);
|
||||
panel.on("NetMonitor:NetworkEventUpdating:ResponseStart", onGenericEvent);
|
||||
panel.on("NetMonitor:NetworkEventUpdating:ResponseContent", onGenericEvent);
|
||||
panel.on("NetMonitor:NetworkEventUpdated:ResponseContent", onGenericEvent);
|
||||
panel.on("NetMonitor:NetworkEventUpdating:EventTimings", onGenericEvent);
|
||||
panel.on("NetMonitor:NetworkEventUpdated:EventTimings", onGenericEvent);
|
||||
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
function verifyRequestItemTarget(aRequestItem, aMethod, aUrl, aData = {}) {
|
||||
info("> Verifying: " + aMethod + " " + aUrl + " " + aData.toSource());
|
||||
info("> Request: " + aRequestItem.attachment.toSource());
|
||||
|
||||
let { status, type, size, time } = aData;
|
||||
let { attachment, target } = aRequestItem
|
||||
|
||||
let uri = Services.io.newURI(aUrl, null, null).QueryInterface(Ci.nsIURL);
|
||||
let name = uri.fileName || "/";
|
||||
let query = uri.query;
|
||||
let hostPort = uri.hostPort;
|
||||
|
||||
is(attachment.method, aMethod,
|
||||
"The attached method is incorrect.");
|
||||
|
||||
is(attachment.url, aUrl,
|
||||
"The attached url is incorrect.");
|
||||
|
||||
is(target.querySelector(".requests-menu-method").getAttribute("value"),
|
||||
aMethod, "The displayed method is incorrect.");
|
||||
|
||||
is(target.querySelector(".requests-menu-file").getAttribute("value"),
|
||||
name + (query ? "?" + query : ""), "The displayed file is incorrect.");
|
||||
|
||||
is(target.querySelector(".requests-menu-domain").getAttribute("value"),
|
||||
hostPort, "The displayed domain is incorrect.");
|
||||
|
||||
if (status !== undefined) {
|
||||
let value = target.querySelector(".requests-menu-status").getAttribute("code");
|
||||
info("Displayed status: " + value);
|
||||
is(value, status, "The displayed status is incorrect.");
|
||||
}
|
||||
if (type !== undefined) {
|
||||
let value = target.querySelector(".requests-menu-type").getAttribute("value");
|
||||
info("Displayed type: " + value);
|
||||
is(value, type, "The displayed type is incorrect.");
|
||||
}
|
||||
if (size !== undefined) {
|
||||
let value = target.querySelector(".requests-menu-size").getAttribute("value");
|
||||
info("Displayed size: " + value);
|
||||
is(value, size, "The displayed size is incorrect.");
|
||||
}
|
||||
if (time !== undefined) {
|
||||
let value = target.querySelector(".requests-menu-timings-total").getAttribute("value");
|
||||
info("Displayed time: " + value);
|
||||
ok(~~(value.match(/[0-9]+/)) >= 0, "The displayed time is incorrect.");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
<!doctype html>
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<title>Network Monitor test page</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<p>Content type test</p>
|
||||
|
||||
<script type="text/javascript">
|
||||
function get(aAddress, aCallback) {
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open("GET", aAddress, true);
|
||||
|
||||
xhr.onreadystatechange = function() {
|
||||
if (this.readyState == this.DONE) {
|
||||
aCallback();
|
||||
}
|
||||
};
|
||||
xhr.send(null);
|
||||
}
|
||||
|
||||
function performRequests() {
|
||||
get("sjs_content-type-test-server.sjs?fmt=xml", function() {
|
||||
get("sjs_content-type-test-server.sjs?fmt=css", function() {
|
||||
get("sjs_content-type-test-server.sjs?fmt=js", function() {
|
||||
get("sjs_content-type-test-server.sjs?fmt=json", function() {
|
||||
get("sjs_content-type-test-server.sjs?fmt=bogus", function() {
|
||||
get("test-image.png", function() {
|
||||
// Done.
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
|
@ -0,0 +1,13 @@
|
|||
<!doctype html>
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<title>Network Monitor test page</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<p>Navigation test</p>
|
||||
</body>
|
||||
|
||||
</html>
|
|
@ -0,0 +1,72 @@
|
|||
<!doctype html>
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<title>Network Monitor test page</title>
|
||||
<style>
|
||||
input {
|
||||
display: block;
|
||||
margin: 12px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<p>POST data test</p>
|
||||
<form enctype="multipart/form-data" method="post" name="form-name">
|
||||
<input type="text" name="text" placeholder="text" value="Some text..."/>
|
||||
<input type="email" name="email" placeholder="email"/>
|
||||
<input type="range" name="range" value="42"/>
|
||||
<input type="button" value="Post me!" onclick="window.form()">
|
||||
</form>
|
||||
|
||||
<script type="text/javascript">
|
||||
function post(aAddress, aMessage, aCallback) {
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open("POST", aAddress, true);
|
||||
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
|
||||
|
||||
var data = "";
|
||||
for (var i in aMessage) {
|
||||
data += "&" + i + "=" + aMessage[i];
|
||||
}
|
||||
|
||||
xhr.onreadystatechange = function() {
|
||||
if (this.readyState == this.DONE) {
|
||||
aCallback();
|
||||
}
|
||||
};
|
||||
xhr.send(data);
|
||||
}
|
||||
|
||||
function form(aAddress, aForm, aCallback) {
|
||||
var formData = new FormData(document.forms.namedItem(aForm));
|
||||
formData.append("Custom field", "Extra data");
|
||||
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open("POST", aAddress, true);
|
||||
|
||||
xhr.onreadystatechange = function() {
|
||||
if (this.readyState == this.DONE) {
|
||||
aCallback();
|
||||
}
|
||||
};
|
||||
xhr.send(formData);
|
||||
}
|
||||
|
||||
function performRequests() {
|
||||
var url = "sjs_simple-test-server.sjs";
|
||||
var url1 = url + "?foo=bar&baz=42&type=urlencoded";
|
||||
var url2 = url + "?foo=bar&baz=42&type=multipart";
|
||||
|
||||
post(url1, { foo: "bar", baz: 123 }, function() {
|
||||
form(url2, "form-name", function() {
|
||||
// Done.
|
||||
});
|
||||
});
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
|
@ -0,0 +1,13 @@
|
|||
<!doctype html>
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<title>Network Monitor test page</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<p>Simple test</p>
|
||||
</body>
|
||||
|
||||
</html>
|
|
@ -0,0 +1,41 @@
|
|||
<!doctype html>
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<title>Network Monitor test page</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<p>Status codes test</p>
|
||||
|
||||
<script type="text/javascript">
|
||||
function get(aAddress, aCallback) {
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open("GET", aAddress, true);
|
||||
|
||||
xhr.onreadystatechange = function() {
|
||||
if (this.readyState == this.DONE) {
|
||||
aCallback();
|
||||
}
|
||||
};
|
||||
xhr.send(null);
|
||||
}
|
||||
|
||||
function performRequests() {
|
||||
get("sjs_status-codes-test-server.sjs?sts=100", function() {
|
||||
get("sjs_status-codes-test-server.sjs?sts=200", function() {
|
||||
get("sjs_status-codes-test-server.sjs?sts=300", function() {
|
||||
get("sjs_status-codes-test-server.sjs?sts=400", function() {
|
||||
get("sjs_status-codes-test-server.sjs?sts=500", function() {
|
||||
// Done.
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
|
@ -0,0 +1,5 @@
|
|||
# vim: set filetype=python:
|
||||
# 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/.
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
const { classes: Cc, interfaces: Ci } = Components;
|
||||
|
||||
function handleRequest(request, response) {
|
||||
response.processAsync();
|
||||
|
||||
let params = request.queryString.split("&");
|
||||
let format = params.filter((s) => s.contains("fmt="))[0].split("=")[1];
|
||||
|
||||
Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer).initWithCallback(() => {
|
||||
switch (format) {
|
||||
case "xml":
|
||||
response.setStatusLine(request.httpVersion, 200, "OK");
|
||||
response.setHeader("Content-Type", "text/xml; charset=utf-8", false);
|
||||
response.write("<label value='greeting'>Hello XML!</label>");
|
||||
response.finish();
|
||||
break;
|
||||
case "css":
|
||||
response.setStatusLine(request.httpVersion, 200, "OK");
|
||||
response.setHeader("Content-Type", "text/css; charset=utf-8", false);
|
||||
response.write("body:pre { content: 'Hello CSS!' }");
|
||||
response.finish();
|
||||
break;
|
||||
case "js":
|
||||
response.setStatusLine(request.httpVersion, 200, "OK");
|
||||
response.setHeader("Content-Type", "application/javascript; charset=utf-8", false);
|
||||
response.write("function() { return 'Hello JS!'; }");
|
||||
response.finish();
|
||||
break;
|
||||
case "json":
|
||||
response.setStatusLine(request.httpVersion, 200, "OK");
|
||||
response.setHeader("Content-Type", "application/json; charset=utf-8", false);
|
||||
response.write("{ \"greeting\": \"Hello JSON!\" }");
|
||||
response.finish();
|
||||
break;
|
||||
default:
|
||||
response.setStatusLine(request.httpVersion, 404, "Not Found");
|
||||
response.setHeader("Content-Type", "text/html; charset=utf-8", false);
|
||||
response.write("<blink>Not Found</blink>");
|
||||
response.finish();
|
||||
break;
|
||||
}
|
||||
}, 10, Ci.nsITimer.TYPE_ONE_SHOT); // Make sure this request takes a few ms.
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
function handleRequest(request, response) {
|
||||
response.setStatusLine(request.httpVersion, 200, "Och Aye");
|
||||
response.setHeader("Content-Type", "text/plain; charset=utf-8", false);
|
||||
response.setHeader("Foo-Bar", "baz", false);
|
||||
response.write("Hello world!");
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
function handleRequest(request, response) {
|
||||
let params = request.queryString.split("&");
|
||||
let status = params.filter((s) => s.contains("sts="))[0].split("=")[1];
|
||||
|
||||
switch (status) {
|
||||
case "100":
|
||||
response.setStatusLine(request.httpVersion, 101, "Switching Protocols");
|
||||
break;
|
||||
case "200":
|
||||
response.setStatusLine(request.httpVersion, 202, "Created");
|
||||
break;
|
||||
case "300":
|
||||
response.setStatusLine(request.httpVersion, 303, "See Other");
|
||||
break;
|
||||
case "400":
|
||||
response.setStatusLine(request.httpVersion, 404, "Not Found");
|
||||
break;
|
||||
case "500":
|
||||
response.setStatusLine(request.httpVersion, 501, "Not Implemented");
|
||||
break;
|
||||
}
|
||||
response.setHeader("Content-Type", "text/plain; charset=utf-8", false);
|
||||
response.write("Hello status code " + status + "!");
|
||||
}
|
Двоичный файл не отображается.
После Ширина: | Высота: | Размер: 580 B |
|
@ -90,7 +90,7 @@ Parser.prototype = {
|
|||
* Clears all the parsed sources from cache.
|
||||
*/
|
||||
clearCache: function P_clearCache() {
|
||||
this._cache = new Map();
|
||||
this._cache.clear();
|
||||
},
|
||||
|
||||
_cache: null
|
||||
|
|
|
@ -81,6 +81,7 @@ SideMenuWidget.prototype = {
|
|||
*/
|
||||
insertItemAt: function SMW_insertItemAt(aIndex, aContents, aTooltip = "", aGroup = "") {
|
||||
this.ensureSelectionIsVisible(true, true); // Don't worry, it's delayed.
|
||||
|
||||
let group = this._getGroupForName(aGroup);
|
||||
return group.insertItemAt(aIndex, aContents, aTooltip);
|
||||
},
|
||||
|
@ -126,7 +127,7 @@ SideMenuWidget.prototype = {
|
|||
}
|
||||
this._selectedItem = null;
|
||||
|
||||
this._groupsByName = new Map();
|
||||
this._groupsByName.clear();
|
||||
this._orderedGroupElementsArray.length = 0;
|
||||
this._orderedMenuElementsArray.length = 0;
|
||||
},
|
||||
|
@ -404,6 +405,9 @@ SideMenuGroup.prototype = {
|
|||
let menuArray = this._menuElementsArray;
|
||||
let item = new SideMenuItem(this, aContents, aTooltip);
|
||||
|
||||
// Invalidate any notices set on the owner widget.
|
||||
this.ownerView.removeAttribute("notice");
|
||||
|
||||
if (aIndex >= 0) {
|
||||
list.insertBefore(item._container, list.childNodes[aIndex]);
|
||||
menuArray.splice(aIndex, 0, item._target);
|
||||
|
@ -411,6 +415,7 @@ SideMenuGroup.prototype = {
|
|||
list.appendChild(item._container);
|
||||
menuArray.push(item._target);
|
||||
}
|
||||
|
||||
return item._target;
|
||||
},
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@ const Ci = Components.interfaces;
|
|||
const Cu = Components.utils;
|
||||
|
||||
const DBG_STRINGS_URI = "chrome://browser/locale/devtools/debugger.properties";
|
||||
const LAZY_EMPTY_DELAY = 150; // ms
|
||||
const LAZY_EXPAND_DELAY = 50; // ms
|
||||
const LAZY_APPEND_DELAY = 100; // ms
|
||||
const LAZY_APPEND_BATCH = 100; // nodes
|
||||
|
@ -20,8 +21,11 @@ Cu.import("resource://gre/modules/Services.jsm");
|
|||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource:///modules/devtools/ViewHelpers.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this,
|
||||
"WebConsoleUtils", "resource://gre/modules/devtools/WebConsoleUtils.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "NetworkHelper",
|
||||
"resource://gre/modules/devtools/NetworkHelper.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "WebConsoleUtils",
|
||||
"resource://gre/modules/devtools/WebConsoleUtils.jsm");
|
||||
|
||||
this.EXPORTED_SYMBOLS = ["VariablesView"];
|
||||
|
||||
|
@ -42,8 +46,11 @@ const STR = Services.strings.createBundle(DBG_STRINGS_URI);
|
|||
*
|
||||
* @param nsIDOMNode aParentNode
|
||||
* The parent node to hold this view.
|
||||
* @param object aFlags [optional]
|
||||
* An object contaning initialization options for this view.
|
||||
* e.g. { lazyEmpty: true, searchEnabled: true ... }
|
||||
*/
|
||||
this.VariablesView = function VariablesView(aParentNode) {
|
||||
this.VariablesView = function VariablesView(aParentNode, aFlags = {}) {
|
||||
this._store = new Map();
|
||||
this._itemsByElement = new WeakMap();
|
||||
this._prevHierarchy = new Map();
|
||||
|
@ -63,6 +70,10 @@ this.VariablesView = function VariablesView(aParentNode) {
|
|||
this._list.addEventListener("keypress", this._onViewKeyPress, false);
|
||||
this._parent.appendChild(this._list);
|
||||
this._boxObject = this._list.boxObject.QueryInterface(Ci.nsIScrollBoxObject);
|
||||
|
||||
for (let name in aFlags) {
|
||||
this[name] = aFlags[name];
|
||||
}
|
||||
};
|
||||
|
||||
VariablesView.prototype = {
|
||||
|
@ -123,8 +134,8 @@ VariablesView.prototype = {
|
|||
list.removeChild(firstChild);
|
||||
}
|
||||
|
||||
this._store = new Map();
|
||||
this._itemsByElement = new WeakMap();
|
||||
this._store.clear();
|
||||
this._itemsByElement.clear();
|
||||
|
||||
this._appendEmptyNotice();
|
||||
this._toggleSearchVisibility(false);
|
||||
|
@ -149,8 +160,8 @@ VariablesView.prototype = {
|
|||
let prevList = this._list;
|
||||
let currList = this._list = this.document.createElement("scrollbox");
|
||||
|
||||
this._store = new Map();
|
||||
this._itemsByElement = new WeakMap();
|
||||
this._store.clear();
|
||||
this._itemsByElement.clear();
|
||||
|
||||
this._emptyTimeout = this.window.setTimeout(function() {
|
||||
this._emptyTimeout = null;
|
||||
|
@ -173,7 +184,7 @@ VariablesView.prototype = {
|
|||
/**
|
||||
* The amount of time (in milliseconds) it takes to empty this view lazily.
|
||||
*/
|
||||
lazyEmptyDelay: 150,
|
||||
lazyEmptyDelay: LAZY_EMPTY_DELAY,
|
||||
|
||||
/**
|
||||
* Specifies if this view may be emptied lazily.
|
||||
|
@ -214,6 +225,12 @@ VariablesView.prototype = {
|
|||
*/
|
||||
delete: null,
|
||||
|
||||
/**
|
||||
* Specifies if after an eval or switch operation, the variable or property
|
||||
* which has been edited should be disabled.
|
||||
*/
|
||||
preventDisableOnChage: false,
|
||||
|
||||
/**
|
||||
* The tooltip text shown on a variable or property's value if an |eval|
|
||||
* function is provided, in order to change the variable or property's value.
|
||||
|
@ -1083,11 +1100,13 @@ Scope.prototype = {
|
|||
* - { value: { type: "object", class: "Object" } }
|
||||
* - { get: { type: "object", class: "Function" },
|
||||
* set: { type: "undefined" } }
|
||||
* @param boolean aRelaxed
|
||||
* True if name duplicates should be allowed.
|
||||
* @return Variable
|
||||
* The newly created Variable instance, null if it already exists.
|
||||
*/
|
||||
addVar: function S_addVar(aName = "", aDescriptor = {}) {
|
||||
if (this._store.has(aName)) {
|
||||
addVar: function S_addVar(aName = "", aDescriptor = {}, aRelaxed = false) {
|
||||
if (this._store.has(aName) && !aRelaxed) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -1855,11 +1874,13 @@ ViewHelpers.create({ constructor: Variable, proto: Scope.prototype }, {
|
|||
* - { value: { type: "object", class: "Object" } }
|
||||
* - { get: { type: "object", class: "Function" },
|
||||
* set: { type: "undefined" } }
|
||||
* @param boolean aRelaxed
|
||||
* True if name duplicates should be allowed.
|
||||
* @return Property
|
||||
* The newly created Property instance, null if it already exists.
|
||||
*/
|
||||
addProperty: function V_addProperty(aName = "", aDescriptor = {}) {
|
||||
if (this._store.has(aName)) {
|
||||
addProperty: function V_addProperty(aName = "", aDescriptor = {}, aRelaxed = false) {
|
||||
if (this._store.has(aName) && !aRelaxed) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -1918,6 +1939,7 @@ ViewHelpers.create({ constructor: Variable, proto: Scope.prototype }, {
|
|||
* @param object aOptions [optional]
|
||||
* Additional options for adding the properties. Supported options:
|
||||
* - sorted: true to sort all the properties before adding them
|
||||
* - expanded: true to expand all the properties after adding them
|
||||
*/
|
||||
populate: function V_populate(aObject, aOptions = {}) {
|
||||
// Retrieve the properties only once.
|
||||
|
@ -1937,9 +1959,15 @@ ViewHelpers.create({ constructor: Variable, proto: Scope.prototype }, {
|
|||
for (let name of propertyNames) {
|
||||
let descriptor = Object.getOwnPropertyDescriptor(aObject, name);
|
||||
if (descriptor.get || descriptor.set) {
|
||||
this._addRawNonValueProperty(name, descriptor);
|
||||
let prop = this._addRawNonValueProperty(name, descriptor);
|
||||
if (aOptions.expanded) {
|
||||
prop.expanded = true;
|
||||
}
|
||||
} else {
|
||||
this._addRawValueProperty(name, descriptor, aObject[name]);
|
||||
let prop = this._addRawValueProperty(name, descriptor, aObject[name]);
|
||||
if (aOptions.expanded) {
|
||||
prop.expanded = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Add the variable's __proto__.
|
||||
|
@ -1972,6 +2000,8 @@ ViewHelpers.create({ constructor: Variable, proto: Scope.prototype }, {
|
|||
* Object.getOwnPropertyDescriptor.
|
||||
* @param object aValue
|
||||
* The raw property value you want to display.
|
||||
* @return Property
|
||||
* The newly added property instance.
|
||||
*/
|
||||
_addRawValueProperty: function V__addRawValueProperty(aName, aDescriptor, aValue) {
|
||||
let descriptor = Object.create(aDescriptor);
|
||||
|
@ -1985,6 +2015,7 @@ ViewHelpers.create({ constructor: Variable, proto: Scope.prototype }, {
|
|||
if (!VariablesView.isPrimitive(descriptor)) {
|
||||
propertyItem.onexpand = this._populateTarget;
|
||||
}
|
||||
return propertyItem;
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -1995,13 +2026,15 @@ ViewHelpers.create({ constructor: Variable, proto: Scope.prototype }, {
|
|||
* @param object aDescriptor
|
||||
* Specifies the exact property descriptor as returned by a call to
|
||||
* Object.getOwnPropertyDescriptor.
|
||||
* @return Property
|
||||
* The newly added property instance.
|
||||
*/
|
||||
_addRawNonValueProperty: function V__addRawNonValueProperty(aName, aDescriptor) {
|
||||
let descriptor = Object.create(aDescriptor);
|
||||
descriptor.get = VariablesView.getGrip(aDescriptor.get);
|
||||
descriptor.set = VariablesView.getGrip(aDescriptor.set);
|
||||
|
||||
this.addProperty(aName, descriptor);
|
||||
return this.addProperty(aName, descriptor);
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -2048,7 +2081,7 @@ ViewHelpers.create({ constructor: Variable, proto: Scope.prototype }, {
|
|||
*/
|
||||
setGrip: function V_setGrip(aGrip) {
|
||||
// Don't allow displaying grip information if there's no name available.
|
||||
if (!this._nameString) {
|
||||
if (!this._nameString || aGrip === undefined || aGrip === null) {
|
||||
return;
|
||||
}
|
||||
// Getters and setters should display grip information in sub-properties.
|
||||
|
@ -2057,11 +2090,9 @@ ViewHelpers.create({ constructor: Variable, proto: Scope.prototype }, {
|
|||
return;
|
||||
}
|
||||
|
||||
if (aGrip === undefined) {
|
||||
aGrip = { type: "undefined" };
|
||||
}
|
||||
if (aGrip === null) {
|
||||
aGrip = { type: "null" };
|
||||
// Make sure the value is escaped unicode if it's a string.
|
||||
if (typeof aGrip == "string") {
|
||||
aGrip = NetworkHelper.convertToUnicode(unescape(aGrip));
|
||||
}
|
||||
|
||||
let prevGrip = this._valueGrip;
|
||||
|
@ -2256,13 +2287,13 @@ ViewHelpers.create({ constructor: Variable, proto: Scope.prototype }, {
|
|||
if (this.ownerView.eval) {
|
||||
this._target.setAttribute("editable", "");
|
||||
}
|
||||
if (!descriptor.configurable) {
|
||||
if (!descriptor.null && !descriptor.configurable) {
|
||||
this._target.setAttribute("non-configurable", "");
|
||||
}
|
||||
if (!descriptor.enumerable) {
|
||||
if (!descriptor.null && !descriptor.enumerable) {
|
||||
this._target.setAttribute("non-enumerable", "");
|
||||
}
|
||||
if (!descriptor.writable && !this.ownerView.getter && !this.ownerView.setter) {
|
||||
if (!descriptor.null && !descriptor.writable && !this.ownerView.getter && !this.ownerView.setter) {
|
||||
this._target.setAttribute("non-writable", "");
|
||||
}
|
||||
if (name == "this") {
|
||||
|
@ -2341,6 +2372,8 @@ ViewHelpers.create({ constructor: Variable, proto: Scope.prototype }, {
|
|||
*/
|
||||
_deactivateInput: function V__deactivateInput(aLabel, aInput, aCallbacks) {
|
||||
aInput.parentNode.replaceChild(aLabel, aInput);
|
||||
this._variablesView._boxObject.scrollBy(-this._target.clientWidth, 0);
|
||||
|
||||
aInput.removeEventListener("keypress", aCallbacks.onKeypress, false);
|
||||
aInput.removeEventListener("blur", aCallbacks.onBlur, false);
|
||||
|
||||
|
@ -2454,8 +2487,10 @@ ViewHelpers.create({ constructor: Variable, proto: Scope.prototype }, {
|
|||
this._deactivateNameInput(e);
|
||||
|
||||
if (initialString != currentString) {
|
||||
this._disable();
|
||||
this._name.value = currentString;
|
||||
if (!this._variablesView.preventDisableOnChage) {
|
||||
this._disable();
|
||||
this._name.value = currentString;
|
||||
}
|
||||
this.ownerView.switch(this, currentString);
|
||||
}
|
||||
},
|
||||
|
@ -2470,7 +2505,9 @@ ViewHelpers.create({ constructor: Variable, proto: Scope.prototype }, {
|
|||
this._deactivateValueInput(e);
|
||||
|
||||
if (initialString != currentString) {
|
||||
this._disable();
|
||||
if (!this._variablesView.preventDisableOnChage) {
|
||||
this._disable();
|
||||
}
|
||||
this.ownerView.eval(this.evaluationMacro(this, currentString.trim()));
|
||||
}
|
||||
},
|
||||
|
@ -2635,8 +2672,8 @@ Property.prototype.__iterator__ = function VV_iterator() {
|
|||
* @see VariablesView.createHierarchy
|
||||
*/
|
||||
VariablesView.prototype.clearHierarchy = function VV_clearHierarchy() {
|
||||
this._prevHierarchy = new Map();
|
||||
this._currHierarchy = new Map();
|
||||
this._prevHierarchy.clear();
|
||||
this._currHierarchy.clear();
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -2645,7 +2682,7 @@ VariablesView.prototype.clearHierarchy = function VV_clearHierarchy() {
|
|||
*/
|
||||
VariablesView.prototype.createHierarchy = function VV_createHierarchy() {
|
||||
this._prevHierarchy = this._currHierarchy;
|
||||
this._currHierarchy = new Map();
|
||||
this._currHierarchy = new Map(); // Don't clear, this is just simple swapping.
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -5,9 +5,15 @@
|
|||
* 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;
|
||||
|
||||
const PANE_APPEARANCE_DELAY = 50;
|
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
||||
this.EXPORTED_SYMBOLS = ["ViewHelpers", "MenuItem", "MenuContainer"];
|
||||
|
||||
/**
|
||||
|
@ -69,7 +75,7 @@ this.ViewHelpers = {
|
|||
* @param nsIDOMNode aNode
|
||||
* A node to delegate the methods to.
|
||||
*/
|
||||
delegateWidgetAttributeMethods: function MC_delegateWidgetAttributeMethods(aWidget, aNode) {
|
||||
delegateWidgetAttributeMethods: function VH_delegateWidgetAttributeMethods(aWidget, aNode) {
|
||||
aWidget.getAttribute = aNode.getAttribute.bind(aNode);
|
||||
aWidget.setAttribute = aNode.setAttribute.bind(aNode);
|
||||
aWidget.removeAttribute = aNode.removeAttribute.bind(aNode);
|
||||
|
@ -84,9 +90,185 @@ this.ViewHelpers = {
|
|||
* @param nsIDOMNode aNode
|
||||
* A node to delegate the methods to.
|
||||
*/
|
||||
delegateWidgetEventMethods: function MC_delegateWidgetEventMethods(aWidget, aNode) {
|
||||
delegateWidgetEventMethods: function VH_delegateWidgetEventMethods(aWidget, aNode) {
|
||||
aWidget.addEventListener = aNode.addEventListener.bind(aNode);
|
||||
aWidget.removeEventListener = aNode.removeEventListener.bind(aNode);
|
||||
},
|
||||
|
||||
/**
|
||||
* Sets a side pane hidden or visible.
|
||||
*
|
||||
* @param object aFlags
|
||||
* An object containing some of the following properties:
|
||||
* - visible: true if the pane should be shown, false to hide
|
||||
* - animated: true to display an animation on toggle
|
||||
* - delayed: true to wait a few cycles before toggle
|
||||
* - callback: a function to invoke when the toggle finishes
|
||||
* @param nsIDOMNode aPane
|
||||
* The element representing the pane to toggle.
|
||||
*/
|
||||
togglePane: function VH_togglePane(aFlags, aPane) {
|
||||
// Avoid useless toggles.
|
||||
if (aFlags.visible == !aPane.hasAttribute("pane-collapsed")) {
|
||||
if (aFlags.callback) aFlags.callback();
|
||||
return;
|
||||
}
|
||||
|
||||
// Computes and sets the pane margins in order to hide or show it.
|
||||
function set() {
|
||||
if (aFlags.visible) {
|
||||
aPane.style.marginLeft = "0";
|
||||
aPane.style.marginRight = "0";
|
||||
aPane.removeAttribute("pane-collapsed");
|
||||
} else {
|
||||
let margin = ~~(aPane.getAttribute("width")) + 1;
|
||||
aPane.style.marginLeft = -margin + "px";
|
||||
aPane.style.marginRight = -margin + "px";
|
||||
aPane.setAttribute("pane-collapsed", "");
|
||||
}
|
||||
|
||||
// Invoke the callback when the transition ended.
|
||||
if (aFlags.animated) {
|
||||
aPane.addEventListener("transitionend", function onEvent() {
|
||||
aPane.removeEventListener("transitionend", onEvent, false);
|
||||
if (aFlags.callback) aFlags.callback();
|
||||
}, false);
|
||||
}
|
||||
// Invoke the callback immediately since there's no transition.
|
||||
else {
|
||||
if (aFlags.callback) aFlags.callback();
|
||||
}
|
||||
}
|
||||
|
||||
// Add a class to the pane to handle min-widths, margins and animations.
|
||||
if (!aPane.classList.contains("generic-toggled-side-pane")) {
|
||||
aPane.classList.add("generic-toggled-side-pane");
|
||||
}
|
||||
|
||||
// Hiding is always handled via margins, not the hidden attribute.
|
||||
aPane.removeAttribute("hidden");
|
||||
|
||||
// The "animated" attributes enables animated toggles (slide in-out).
|
||||
if (aFlags.animated) {
|
||||
aPane.setAttribute("animated", "");
|
||||
} else {
|
||||
aPane.removeAttribute("animated");
|
||||
}
|
||||
|
||||
// Sometimes it's useful delaying the toggle a few ticks to ensure
|
||||
// a smoother slide in-out animation.
|
||||
if (aFlags.delayed) {
|
||||
aPane.ownerDocument.defaultView.setTimeout(set.bind(this), PANE_APPEARANCE_DELAY);
|
||||
} else {
|
||||
set.call(this);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Localization convenience methods.
|
||||
*
|
||||
* @param string aStringBundleName
|
||||
* The desired string bundle's name.
|
||||
*/
|
||||
ViewHelpers.L10N = function L10N(aStringBundleName) {
|
||||
XPCOMUtils.defineLazyGetter(this, "stringBundle", () =>
|
||||
Services.strings.createBundle(aStringBundleName));
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "ellipsis", () =>
|
||||
Services.prefs.getComplexValue("intl.ellipsis", Ci.nsIPrefLocalizedString).data);
|
||||
};
|
||||
|
||||
ViewHelpers.L10N.prototype = {
|
||||
stringBundle: null,
|
||||
|
||||
/**
|
||||
* L10N shortcut function.
|
||||
*
|
||||
* @param string aName
|
||||
* @return string
|
||||
*/
|
||||
getStr: function L10N_getStr(aName) {
|
||||
return this.stringBundle.GetStringFromName(aName);
|
||||
},
|
||||
|
||||
/**
|
||||
* L10N shortcut function.
|
||||
*
|
||||
* @param string aName
|
||||
* @param array aArgs
|
||||
* @return string
|
||||
*/
|
||||
getFormatStr: function L10N_getFormatStr(aName, ...aArgs) {
|
||||
return this.stringBundle.formatStringFromName(aName, aArgs, aArgs.length);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Shortcuts for lazily accessing and setting various preferences.
|
||||
* Usage:
|
||||
* let prefs = new ViewHelpers.Prefs("root.path.to.branch", {
|
||||
* myIntPref: ["Int", "leaf.path.to.my-int-pref"],
|
||||
* myCharPref: ["Char", "leaf.path.to.my-char-pref"],
|
||||
* ...
|
||||
* });
|
||||
*
|
||||
* prefs.myCharPref = "foo";
|
||||
* let aux = prefs.myCharPref;
|
||||
*
|
||||
* @param string aPrefsRoot
|
||||
* The root path to the required preferences branch.
|
||||
* @param object aPrefsObject
|
||||
* An object containing { accessorName: [prefType, prefName] } keys.
|
||||
*/
|
||||
ViewHelpers.Prefs = function Prefs(aPrefsRoot = "", aPrefsObject = {}) {
|
||||
this.root = aPrefsRoot;
|
||||
|
||||
for (let accessorName in aPrefsObject) {
|
||||
let [prefType, prefName] = aPrefsObject[accessorName];
|
||||
this.map(accessorName, prefType, prefName);
|
||||
}
|
||||
};
|
||||
|
||||
ViewHelpers.Prefs.prototype = {
|
||||
/**
|
||||
* Helper method for getting a pref value.
|
||||
*
|
||||
* @param string aType
|
||||
* @param string aPrefName
|
||||
* @return any
|
||||
*/
|
||||
_get: function P__get(aType, aPrefName) {
|
||||
if (this[aPrefName] === undefined) {
|
||||
this[aPrefName] = Services.prefs["get" + aType + "Pref"](aPrefName);
|
||||
}
|
||||
return this[aPrefName];
|
||||
},
|
||||
|
||||
/**
|
||||
* Helper method for setting a pref value.
|
||||
*
|
||||
* @param string aType
|
||||
* @param string aPrefName
|
||||
* @param any aValue
|
||||
*/
|
||||
_set: function P__set(aType, aPrefName, aValue) {
|
||||
Services.prefs["set" + aType + "Pref"](aPrefName, aValue);
|
||||
this[aPrefName] = aValue;
|
||||
},
|
||||
|
||||
/**
|
||||
* Maps a property name to a pref, defining lazy getters and setters.
|
||||
*
|
||||
* @param string aAccessorName
|
||||
* @param string aType
|
||||
* @param string aPrefName
|
||||
*/
|
||||
map: function P_map(aAccessorName, aType, aPrefName) {
|
||||
Object.defineProperty(this, aAccessorName, {
|
||||
get: () => this._get(aType, [this.root, aPrefName].join(".")),
|
||||
set: (aValue) => this._set(aType, [this.root, aPrefName].join("."), aValue)
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -219,7 +401,7 @@ MenuItem.prototype = {
|
|||
*/
|
||||
_entangleItem: function MI__entangleItem(aItem, aElement) {
|
||||
if (!this._itemsByElement) {
|
||||
this._itemsByElement = new Map();
|
||||
this._itemsByElement = new Map(); // This needs to be iterable.
|
||||
}
|
||||
|
||||
this._itemsByElement.set(aElement, aItem);
|
||||
|
@ -249,7 +431,13 @@ MenuItem.prototype = {
|
|||
* @return string
|
||||
*/
|
||||
toString: function MI_toString() {
|
||||
return this._label + " -> " + this._value;
|
||||
if (this._label && this._value) {
|
||||
return this._label + " -> " + this._value;
|
||||
}
|
||||
if (this.attachment) {
|
||||
return this.attachment.toString();
|
||||
}
|
||||
return "(null)";
|
||||
},
|
||||
|
||||
_label: "",
|
||||
|
@ -345,7 +533,7 @@ MenuContainer.prototype = {
|
|||
aContents instanceof Ci.nsIDOMElement) {
|
||||
// Allow the insertion of prebuilt nodes.
|
||||
aOptions.node = aContents;
|
||||
aContents = [];
|
||||
aContents = ["", "", ""];
|
||||
}
|
||||
|
||||
let [label, value, description] = aContents;
|
||||
|
@ -435,9 +623,9 @@ MenuContainer.prototype = {
|
|||
this._untangleItem(item);
|
||||
}
|
||||
|
||||
this._itemsByLabel = new Map();
|
||||
this._itemsByValue = new Map();
|
||||
this._itemsByElement = new Map();
|
||||
this._itemsByLabel.clear();
|
||||
this._itemsByValue.clear();
|
||||
this._itemsByElement.clear();
|
||||
this._stagedItems.length = 0;
|
||||
},
|
||||
|
||||
|
@ -517,7 +705,7 @@ MenuContainer.prototype = {
|
|||
if (selectedElement) {
|
||||
return this._itemsByElement.get(selectedElement);
|
||||
}
|
||||
return -1;
|
||||
return null;
|
||||
},
|
||||
|
||||
/**
|
||||
|
|
|
@ -0,0 +1,130 @@
|
|||
<!-- 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/. -->
|
||||
|
||||
<!-- LOCALIZATION NOTE : FILE This file contains the Network Monitor strings -->
|
||||
<!-- LOCALIZATION NOTE : FILE Do not translate commandkey -->
|
||||
|
||||
<!-- LOCALIZATION NOTE : FILE The correct localization of this file might be to
|
||||
- keep it in English, or another language commonly spoken among web developers.
|
||||
- You want to make that choice consistent across the developer tools.
|
||||
- A good criteria is the language in which you'd find the best
|
||||
- documentation on web development on the web. -->
|
||||
|
||||
<!-- LOCALIZATION NOTE (netmonitorUI.emptyNotice): This is the label displayed
|
||||
- in the network table when empty. -->
|
||||
<!ENTITY netmonitorUI.emptyNotice "Reload the page to see detailed information about network activity.">
|
||||
|
||||
<!-- LOCALIZATION NOTE (netmonitorUI.toolbar.method): This is the label displayed
|
||||
- in the network table toolbar, above the "method" column. -->
|
||||
<!ENTITY netmonitorUI.toolbar.method "Method">
|
||||
|
||||
<!-- LOCALIZATION NOTE (netmonitorUI.toolbar.file): This is the label displayed
|
||||
- in the network table toolbar, above the "file" column. -->
|
||||
<!ENTITY netmonitorUI.toolbar.file "File">
|
||||
|
||||
<!-- LOCALIZATION NOTE (netmonitorUI.toolbar.domain): This is the label displayed
|
||||
- in the network table toolbar, above the "domain" column. -->
|
||||
<!ENTITY netmonitorUI.toolbar.domain "Domain">
|
||||
|
||||
<!-- LOCALIZATION NOTE (netmonitorUI.toolbar.type): This is the label displayed
|
||||
- in the network table toolbar, above the "type" column. -->
|
||||
<!ENTITY netmonitorUI.toolbar.type "Type">
|
||||
|
||||
<!-- LOCALIZATION NOTE (netmonitorUI.toolbar.size): This is the label displayed
|
||||
- in the network table toolbar, above the "size" column. -->
|
||||
<!ENTITY netmonitorUI.toolbar.size "Size">
|
||||
|
||||
<!-- LOCALIZATION NOTE (netmonitorUI.toolbar.waterfall): This is the label displayed
|
||||
- in the network table toolbar, above the "waterfall" column. -->
|
||||
<!ENTITY netmonitorUI.toolbar.waterfall "Timeline">
|
||||
|
||||
<!-- LOCALIZATION NOTE (debuggerUI.tab.headers): This is the label displayed
|
||||
- in the network details pane identifying the headers tab. -->
|
||||
<!ENTITY netmonitorUI.tab.headers "Headers">
|
||||
|
||||
<!-- LOCALIZATION NOTE (debuggerUI.tab.cookies): This is the label displayed
|
||||
- in the network details pane identifying the cookies tab. -->
|
||||
<!ENTITY netmonitorUI.tab.cookies "Cookies">
|
||||
|
||||
<!-- LOCALIZATION NOTE (debuggerUI.tab.params): This is the label displayed
|
||||
- in the network details pane identifying the params tab. -->
|
||||
<!ENTITY netmonitorUI.tab.params "Params">
|
||||
|
||||
<!-- LOCALIZATION NOTE (debuggerUI.tab.response): This is the label displayed
|
||||
- in the network details pane identifying the response tab. -->
|
||||
<!ENTITY netmonitorUI.tab.response "Response">
|
||||
|
||||
<!-- LOCALIZATION NOTE (debuggerUI.tab.timings): This is the label displayed
|
||||
- in the network details pane identifying the timings tab. -->
|
||||
<!ENTITY netmonitorUI.tab.timings "Timings">
|
||||
|
||||
<!-- LOCALIZATION NOTE (debuggerUI.panesButton.tooltip): This is the tooltip for
|
||||
- the button that toggles the panes visible or hidden in the netmonitor UI. -->
|
||||
<!ENTITY netmonitorUI.panesButton.tooltip "Toggle network info">
|
||||
|
||||
<!-- LOCALIZATION NOTE (debuggerUI.summary.url): This is the label displayed
|
||||
- in the network details headers tab identifying the URL. -->
|
||||
<!ENTITY netmonitorUI.summary.url "Request URL:">
|
||||
|
||||
<!-- LOCALIZATION NOTE (debuggerUI.summary.method): This is the label displayed
|
||||
- in the network details headers tab identifying the method. -->
|
||||
<!ENTITY netmonitorUI.summary.method "Request method:">
|
||||
|
||||
<!-- LOCALIZATION NOTE (debuggerUI.summary.status): This is the label displayed
|
||||
- in the network details headers tab identifying the status code. -->
|
||||
<!ENTITY netmonitorUI.summary.status "Status code:">
|
||||
|
||||
<!-- LOCALIZATION NOTE (debuggerUI.summary.version): This is the label displayed
|
||||
- in the network details headers tab identifying the http version. -->
|
||||
<!ENTITY netmonitorUI.summary.version "Version:">
|
||||
|
||||
<!-- LOCALIZATION NOTE (debuggerUI.summary.size): This is the label displayed
|
||||
- in the network details headers tab identifying the headers size. -->
|
||||
<!ENTITY netmonitorUI.summary.size "Headers size:">
|
||||
|
||||
<!-- LOCALIZATION NOTE (debuggerUI.response.name): This is the label displayed
|
||||
- in the network details response tab identifying an image's file name. -->
|
||||
<!ENTITY netmonitorUI.response.name "Name:">
|
||||
|
||||
<!-- LOCALIZATION NOTE (debuggerUI.response.dimensions): This is the label displayed
|
||||
- in the network details response tab identifying an image's dimensions. -->
|
||||
<!ENTITY netmonitorUI.response.dimensions "Dimensions:">
|
||||
|
||||
<!-- LOCALIZATION NOTE (debuggerUI.response.mime): This is the label displayed
|
||||
- in the network details response tab identifying an image's mime. -->
|
||||
<!ENTITY netmonitorUI.response.mime "MIME Type:">
|
||||
|
||||
<!-- LOCALIZATION NOTE (debuggerUI.response.encoding): This is the label displayed
|
||||
- in the network details response tab identifying an image's encoding. -->
|
||||
<!ENTITY netmonitorUI.response.encoding "Encoding:">
|
||||
|
||||
<!-- LOCALIZATION NOTE (debuggerUI.timings.blocked): This is the label displayed
|
||||
- in the network details timings tab identifying the amount of time spent
|
||||
- in a "blocked" state. -->
|
||||
<!ENTITY netmonitorUI.timings.blocked "Blocked:">
|
||||
|
||||
<!-- LOCALIZATION NOTE (debuggerUI.timings.dns): This is the label displayed
|
||||
- in the network details timings tab identifying the amount of time spent
|
||||
- in a "dns" state. -->
|
||||
<!ENTITY netmonitorUI.timings.dns "DNS resolution:">
|
||||
|
||||
<!-- LOCALIZATION NOTE (debuggerUI.timings.connect): This is the label displayed
|
||||
- in the network details timings tab identifying the amount of time spent
|
||||
- in a "connect" state. -->
|
||||
<!ENTITY netmonitorUI.timings.connect "Connecting:">
|
||||
|
||||
<!-- LOCALIZATION NOTE (debuggerUI.timings.send): This is the label displayed
|
||||
- in the network details timings tab identifying the amount of time spent
|
||||
- in a "send" state. -->
|
||||
<!ENTITY netmonitorUI.timings.send "Sending:">
|
||||
|
||||
<!-- LOCALIZATION NOTE (debuggerUI.timings.wait): This is the label displayed
|
||||
- in the network details timings tab identifying the amount of time spent
|
||||
- in a "wait" state. -->
|
||||
<!ENTITY netmonitorUI.timings.wait "Waiting:">
|
||||
|
||||
<!-- LOCALIZATION NOTE (debuggerUI.timings.receive): This is the label displayed
|
||||
- in the network details timings tab identifying the amount of time spent
|
||||
- in a "receive" state. -->
|
||||
<!ENTITY netmonitorUI.timings.receive "Receiving:">
|
|
@ -0,0 +1,98 @@
|
|||
# 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/.
|
||||
|
||||
# LOCALIZATION NOTE These strings are used inside the Network Monitor
|
||||
# which is available from the Web Developer sub-menu -> 'Network Monitor'.
|
||||
# The correct localization of this file might be to keep it in
|
||||
# English, or another language commonly spoken among web developers.
|
||||
# You want to make that choice consistent across the developer tools.
|
||||
# A good criteria is the language in which you'd find the best
|
||||
# documentation on web development on the web.
|
||||
|
||||
# LOCALIZATION NOTE (netmonitor.label):
|
||||
# This string is displayed in the title of the tab when the Network Monitor is
|
||||
# displayed inside the developer tools window and in the Developer Tools Menu.
|
||||
netmonitor.label=Network
|
||||
|
||||
# LOCALIZATION NOTE (netmonitor.commandkey, netmonitor.accesskey)
|
||||
# Used for the menuitem in the tool menu
|
||||
netmonitor.commandkey=Q
|
||||
netmonitor.accesskey=N
|
||||
|
||||
# LOCALIZATION NOTE (netmonitor.tooltip):
|
||||
# This string is displayed in the tooltip of the tab when the Network Monitor is
|
||||
# displayed inside the developer tools window.
|
||||
netmonitor.tooltip=Network Monitor
|
||||
|
||||
# LOCALIZATION NOTE (collapseDetailsPane): This is the tooltip for the button
|
||||
# that collapses the network details pane in the UI.
|
||||
collapseDetailsPane=Hide request details
|
||||
|
||||
# LOCALIZATION NOTE (expandDetailsPane): This is the tooltip for the button
|
||||
# that expands the network details pane in the UI.
|
||||
expandDetailsPane=Show request details
|
||||
|
||||
# LOCALIZATION NOTE (headersEmptyText): This is the text displayed in the
|
||||
# headers tab of the network details pane when there are no headers available.
|
||||
headersEmptyText=No headers for this request
|
||||
|
||||
# LOCALIZATION NOTE (headersFilterText): This is the text displayed in the
|
||||
# headers tab of the network details pane for the filtering input.
|
||||
headersFilterText=Filter headers
|
||||
|
||||
# LOCALIZATION NOTE (cookiesEmptyText): This is the text displayed in the
|
||||
# cookies tab of the network details pane when there are no cookies available.
|
||||
cookiesEmptyText=No cookies for this request
|
||||
|
||||
# LOCALIZATION NOTE (cookiesFilterText): This is the text displayed in the
|
||||
# cookies tab of the network details pane for the filtering input.
|
||||
cookiesFilterText=Filter cookies
|
||||
|
||||
# LOCALIZATION NOTE (paramsEmptyText): This is the text displayed in the
|
||||
# params tab of the network details pane when there are no params available.
|
||||
paramsEmptyText=No parameters for this request
|
||||
|
||||
# LOCALIZATION NOTE (paramsFilterText): This is the text displayed in the
|
||||
# params tab of the network details pane for the filtering input.
|
||||
paramsFilterText=Filter request parameters
|
||||
|
||||
# LOCALIZATION NOTE (paramsQueryString): This is the label displayed
|
||||
# in the network details params tab identifying the query string.
|
||||
paramsQueryString=Query string
|
||||
|
||||
# LOCALIZATION NOTE (paramsFormData): This is the label displayed
|
||||
# in the network details params tab identifying the form data.
|
||||
paramsFormData=Form data
|
||||
|
||||
# LOCALIZATION NOTE (paramsPostPayload): This is the label displayed
|
||||
# in the network details params tab identifying the request payload.
|
||||
paramsPostPayload=Request payload
|
||||
|
||||
# LOCALIZATION NOTE (requestHeaders): This is the label displayed
|
||||
# in the network details headers tab identifying the request headers.
|
||||
requestHeaders=Request headers
|
||||
|
||||
# LOCALIZATION NOTE (responseHeaders): This is the label displayed
|
||||
# in the network details headers tab identifying the response headers.
|
||||
responseHeaders=Response headers
|
||||
|
||||
# LOCALIZATION NOTE (requestCookies): This is the label displayed
|
||||
# in the network details params tab identifying the request cookies.
|
||||
requestCookies=Request cookies
|
||||
|
||||
# LOCALIZATION NOTE (responseCookies): This is the label displayed
|
||||
# in the network details params tab identifying the response cookies.
|
||||
responseCookies=Response cookies
|
||||
|
||||
# LOCALIZATION NOTE (jsonFilterText): This is the text displayed
|
||||
# in the response tab of the network details pane for the JSON filtering input.
|
||||
jsonFilterText=Filter properties
|
||||
|
||||
# LOCALIZATION NOTE (networkMenu.size): This is the label displayed
|
||||
# in the network menu specifying the size of a request (in kb).
|
||||
networkMenu.size=%Skb
|
||||
|
||||
# LOCALIZATION NOTE (networkMenu.total): This is the label displayed
|
||||
# in the network menu specifying the time for a request to finish (in ms).
|
||||
networkMenu.total=→ %Sms
|
|
@ -24,6 +24,8 @@
|
|||
locale/browser/browser.properties (%chrome/browser/browser.properties)
|
||||
locale/browser/devtools/debugger.dtd (%chrome/browser/devtools/debugger.dtd)
|
||||
locale/browser/devtools/debugger.properties (%chrome/browser/devtools/debugger.properties)
|
||||
locale/browser/devtools/netmonitor.dtd (%chrome/browser/devtools/netmonitor.dtd)
|
||||
locale/browser/devtools/netmonitor.properties (%chrome/browser/devtools/netmonitor.properties)
|
||||
locale/browser/devtools/gcli.properties (%chrome/browser/devtools/gcli.properties)
|
||||
locale/browser/devtools/gclicommands.properties (%chrome/browser/devtools/gclicommands.properties)
|
||||
locale/browser/devtools/webconsole.properties (%chrome/browser/devtools/webconsole.properties)
|
||||
|
|
|
@ -256,7 +256,7 @@
|
|||
|
||||
.devtools-sidebar-tabs > tabs > tab {
|
||||
-moz-appearance: none;
|
||||
/* We want to match the height of a toolbar with a toolbarbutton
|
||||
/* We want to match the height of a toolbar with a toolbarbutton
|
||||
* First, we need to replicated the padding of toolbar (4px),
|
||||
* then, the padding of the button itself from toolbarbutton.css (3px),
|
||||
* Also, we need to take the border of the buttons into accout (1px).
|
||||
|
|
|
@ -17,20 +17,6 @@
|
|||
-moz-border-start-color: transparent;
|
||||
}
|
||||
|
||||
/* Watch expressions, variables and other instruments pane */
|
||||
|
||||
#instruments-pane {
|
||||
min-width: 50px;
|
||||
-moz-margin-start: 0px !important;
|
||||
/* Unfortunately, transitions don't work properly with locale-aware properties,
|
||||
so both the left and right margins are set via js, while the start margin
|
||||
is always overridden here. */
|
||||
}
|
||||
|
||||
#instruments-pane[animated] {
|
||||
transition: margin 0.25s ease-in-out;
|
||||
}
|
||||
|
||||
/* ListWidget items */
|
||||
|
||||
.list-widget-item {
|
||||
|
@ -310,12 +296,12 @@
|
|||
background: none;
|
||||
box-shadow: none;
|
||||
border: none;
|
||||
list-style-image: url("chrome://browser/skin/devtools/debugger-expand.png");
|
||||
list-style-image: url("chrome://browser/skin/devtools/debugger-collapse.png");
|
||||
-moz-image-region: rect(0px,16px,16px,0px);
|
||||
}
|
||||
|
||||
#instruments-pane-toggle:not([toggled]) {
|
||||
list-style-image: url("chrome://browser/skin/devtools/debugger-collapse.png");
|
||||
#instruments-pane-toggle[pane-collapsed] {
|
||||
list-style-image: url("chrome://browser/skin/devtools/debugger-expand.png");
|
||||
}
|
||||
|
||||
#instruments-pane-toggle:active {
|
||||
|
|
|
@ -0,0 +1,304 @@
|
|||
/* vim:set ts=2 sw=2 sts=2 et: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/* Network requests table */
|
||||
|
||||
#body {
|
||||
background: url(background-noise-toolbar.png), hsl(208,11%,27%);
|
||||
}
|
||||
|
||||
.requests-menu-empty-notice {
|
||||
background: url(background-noise-toolbar.png), hsl(208,11%,27%);
|
||||
padding: 12px;
|
||||
font-size: 110%;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
#requests-menu-toolbar {
|
||||
-moz-padding-start: 4px;
|
||||
}
|
||||
|
||||
.requests-menu-header {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.requests-menu-subitem {
|
||||
padding: 0 4px;
|
||||
}
|
||||
|
||||
.requests-menu-header:not(:last-of-type),
|
||||
.requests-menu-subitem:not(:last-child) {
|
||||
-moz-border-end: 1px solid hsla(210,8%,5%,.25);
|
||||
box-shadow: 1px 0 0 hsla(210,16%,76%,.1);
|
||||
}
|
||||
|
||||
.requests-menu-status-and-method {
|
||||
width: 6em;
|
||||
}
|
||||
|
||||
.requests-menu-status {
|
||||
background: #fff;
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
-moz-margin-start: 4px;
|
||||
-moz-margin-end: 2px;
|
||||
border-radius: 20px;
|
||||
box-shadow:
|
||||
0 0 0 1px rgba(255,255,255,0.4) inset,
|
||||
0 -6px 4px 0 rgba(32,32,32,1.0) inset,
|
||||
0 0 8px 0 rgba(32,0,0,0.4);
|
||||
transition: box-shadow 0.5s ease-in-out;
|
||||
}
|
||||
|
||||
.requests-menu-status[code^="1"] {
|
||||
box-shadow:
|
||||
0 0 2px 1px rgba(255,255,255,0.8) inset,
|
||||
0 -6px 4px 0 rgba(0,0,64,1.0) inset,
|
||||
0 0 8px 0 rgba(0,0,128,1.0);
|
||||
}
|
||||
|
||||
.requests-menu-status[code^="2"] {
|
||||
box-shadow:
|
||||
0 0 2px 1px rgba(255,255,255,0.8) inset,
|
||||
0 -6px 4px 0 rgba(0,64,0,1.0) inset,
|
||||
0 0 8px 0 rgba(0,128,0,1.0);
|
||||
}
|
||||
|
||||
.requests-menu-status[code^="3"] {
|
||||
box-shadow:
|
||||
0 0 2px 1px rgba(255,255,255,0.8) inset,
|
||||
0 -6px 4px 0 rgba(64,32,0,1.0) inset,
|
||||
0 0 8px 0 rgba(128,128,0,1.0);
|
||||
}
|
||||
|
||||
.requests-menu-status[code^="4"] {
|
||||
box-shadow:
|
||||
0 0 2px 1px rgba(255,255,255,0.8) inset,
|
||||
0 -6px 4px 0 rgba(64,0,0,1.0) inset,
|
||||
0 0 8px 0 rgba(128,0,0,1.0);
|
||||
}
|
||||
|
||||
.requests-menu-status[code^="5"] {
|
||||
box-shadow:
|
||||
0 0 2px 1px rgba(255,255,255,0.8) inset,
|
||||
0 -6px 4px 0 rgba(64,0,64,1.0) inset,
|
||||
0 0 8px 0 rgba(128,0,128,1.0);
|
||||
}
|
||||
|
||||
.requests-menu-method {
|
||||
text-align: center;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.requests-menu-file {
|
||||
width: 14em;
|
||||
}
|
||||
|
||||
.requests-menu-domain {
|
||||
width: 14em;
|
||||
}
|
||||
|
||||
.requests-menu-type {
|
||||
text-align: center;
|
||||
width: 4em;
|
||||
}
|
||||
|
||||
.requests-menu-size {
|
||||
text-align: center;
|
||||
width: 6em;
|
||||
}
|
||||
|
||||
.requests-menu-header.requests-menu-waterfall {
|
||||
-moz-padding-start: 8px;
|
||||
-moz-padding-end: 8px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/* Network request waterfall */
|
||||
|
||||
.requests-menu-subitem.requests-menu-waterfall {
|
||||
-moz-padding-start: 4px;
|
||||
-moz-padding-end: 4px;
|
||||
background-size: 5px;
|
||||
background-image:
|
||||
-moz-linear-gradient(left,
|
||||
transparent 25%,
|
||||
rgba(255,255,255,0.02) 25%,
|
||||
rgba(255,255,255,0.02) 75%,
|
||||
transparent 75%);
|
||||
}
|
||||
|
||||
.requests-menu-timings {
|
||||
transform-origin: left center;
|
||||
}
|
||||
|
||||
.requests-menu-timings-total {
|
||||
-moz-padding-start: 4px;
|
||||
font-size: 85%;
|
||||
font-weight: 600;
|
||||
transform-origin: -4px center; /* negative cap size */
|
||||
}
|
||||
|
||||
.requests-menu-timings-cap {
|
||||
width: 4px;
|
||||
height: 10px;
|
||||
border: 1px solid #fff;
|
||||
}
|
||||
|
||||
.requests-menu-timings-cap.start {
|
||||
-moz-border-end: none;
|
||||
border-radius: 4px 0 0 4px;
|
||||
transform-origin: right center;
|
||||
}
|
||||
|
||||
.requests-menu-timings-cap.end {
|
||||
-moz-border-start: none;
|
||||
border-radius: 0 4px 4px 0;
|
||||
transform-origin: left center;
|
||||
}
|
||||
|
||||
.requests-menu-timings-box {
|
||||
height: 10px;
|
||||
border-top: 1px solid #fff;
|
||||
border-bottom: 1px solid #fff;
|
||||
}
|
||||
|
||||
.requests-menu-timings-box.blocked,
|
||||
.requests-menu-timings-cap.blocked {
|
||||
background-color: rgba(255,32,32,0.8);
|
||||
box-shadow: 0 0 8px 0 rgba(128,32,32,0.8),
|
||||
0 0 4px 0 rgba(255,255,255,1.0) inset;
|
||||
}
|
||||
|
||||
.requests-menu-timings-box.dns,
|
||||
.requests-menu-timings-cap.dns {
|
||||
background-color: rgba(255,128,255,0.6);
|
||||
box-shadow: 0 0 8px 0 rgba(128,128,255,1.0),
|
||||
0 0 4px 0 rgba(255,255,255,1.0) inset;
|
||||
}
|
||||
|
||||
.requests-menu-timings-box.connect,
|
||||
.requests-menu-timings-cap.connect {
|
||||
background-color: rgba(255,128,16,0.4);
|
||||
box-shadow: 0 0 8px 0 rgba(128,128,16,0.8),
|
||||
0 0 4px 0 rgba(255,255,255,1.0) inset;
|
||||
}
|
||||
|
||||
.requests-menu-timings-box.send,
|
||||
.requests-menu-timings-cap.send {
|
||||
background-color: rgba(255,255,128,0.4);
|
||||
box-shadow: 0 0 8px 0 rgba(128,255,128,0.8),
|
||||
0 0 4px 0 rgba(255,255,255,1.0) inset;
|
||||
}
|
||||
|
||||
.requests-menu-timings-box.wait,
|
||||
.requests-menu-timings-cap.wait {
|
||||
background-color: rgba(255,255,255,0.2);
|
||||
box-shadow: 0 0 8px 0 rgba(128,255,255,0.4),
|
||||
0 0 4px 0 rgba(255,255,255,1.0) inset;
|
||||
}
|
||||
|
||||
.requests-menu-timings-box.receive,
|
||||
.requests-menu-timings-cap.receive {
|
||||
background-color: rgba(255,255,255,1.0);
|
||||
box-shadow: 0 0 8px 0 rgba(128,255,255,1.0),
|
||||
0 0 4px 0 rgba(255,255,255,1.0) inset;
|
||||
}
|
||||
|
||||
.side-menu-widget-container,
|
||||
.side-menu-widget-item-or-group {
|
||||
box-shadow: none !important;
|
||||
}
|
||||
|
||||
.side-menu-widget-item:nth-child(even) {
|
||||
background: rgba(255,255,255,0.05);
|
||||
}
|
||||
|
||||
/* Network request details */
|
||||
|
||||
#details-pane {
|
||||
background: hsl(208,11%,27%);
|
||||
max-width: 500px;
|
||||
}
|
||||
|
||||
#details-pane-toggle {
|
||||
background: none;
|
||||
box-shadow: none;
|
||||
border-color: transparent;
|
||||
list-style-image: url("chrome://browser/skin/devtools/debugger-collapse.png");
|
||||
-moz-image-region: rect(0px,16px,16px,0px);
|
||||
}
|
||||
|
||||
#details-pane-toggle[pane-collapsed] {
|
||||
list-style-image: url("chrome://browser/skin/devtools/debugger-expand.png");
|
||||
}
|
||||
|
||||
#details-pane-toggle:active {
|
||||
-moz-image-region: rect(0px,32px,16px,16px);
|
||||
}
|
||||
|
||||
/* Network request details tabpanels */
|
||||
|
||||
.tabpanel-content {
|
||||
background: url(background-noise-toolbar.png), #3e4750;
|
||||
box-shadow: 0 1px 0 hsla(204,45%,98%,.05) inset;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.tabpanel-summary-container {
|
||||
padding: 1px;
|
||||
}
|
||||
|
||||
.tabpanel-summary-label {
|
||||
-moz-padding-start: 4px;
|
||||
-moz-padding-end: 3px;
|
||||
font-weight: 600;
|
||||
text-shadow: 0 1px 0 #000;
|
||||
color: hsl(210,30%,85%);
|
||||
}
|
||||
|
||||
.tabpanel-summary-value {
|
||||
-moz-padding-start: 3px;
|
||||
font-family: Menlo, Monaco, monospace;
|
||||
}
|
||||
|
||||
/* Headers tabpanel */
|
||||
|
||||
#headers-summary-status,
|
||||
#headers-summary-version {
|
||||
padding-bottom: 2px;
|
||||
}
|
||||
|
||||
#headers-summary-size {
|
||||
padding-top: 2px;
|
||||
}
|
||||
|
||||
/* Response tabpanel */
|
||||
|
||||
#response-content-image-box {
|
||||
padding-top: 10px;
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
|
||||
#response-content-image {
|
||||
background: #fff;
|
||||
border: 1px dashed GrayText;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
/* Timings tabpanel */
|
||||
|
||||
#timings-tabpanel .tabpanel-summary-label {
|
||||
width: 10em;
|
||||
}
|
||||
|
||||
#timings-tabpanel .requests-menu-timings-box {
|
||||
transition: transform 0.2s ease-out;
|
||||
min-width: 1px;
|
||||
}
|
||||
|
||||
#timings-tabpanel .requests-menu-timings-total {
|
||||
transition: transform 0.2s ease-out;
|
||||
}
|
|
@ -3,6 +3,20 @@
|
|||
* 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/. */
|
||||
|
||||
/* Generic pane helpers */
|
||||
|
||||
.generic-toggled-side-pane {
|
||||
min-width: 50px;
|
||||
-moz-margin-start: 0px !important;
|
||||
/* Unfortunately, transitions don't work properly with locale-aware properties,
|
||||
so both the left and right margins are set via js, while the start margin
|
||||
is always overridden here. */
|
||||
}
|
||||
|
||||
.generic-toggled-side-pane[animated] {
|
||||
transition: margin 0.25s ease-in-out;
|
||||
}
|
||||
|
||||
/* BreacrumbsWidget */
|
||||
|
||||
.breadcrumbs-widget-container {
|
||||
|
@ -298,7 +312,7 @@
|
|||
}
|
||||
|
||||
.side-menu-widget-item.selected {
|
||||
background: -moz-linear-gradient(hsl(206,61%,40%), hsl(206,61%,31%)) repeat-x top left;
|
||||
background: -moz-linear-gradient(hsl(206,61%,40%), hsl(206,61%,31%)) repeat-x top left !important;
|
||||
box-shadow: inset 0 1px 0 hsla(210,40%,83%,.15),
|
||||
inset 0 -1px 0 hsla(210,40%,83%,.05);
|
||||
border-top: 0;
|
||||
|
@ -330,7 +344,7 @@
|
|||
padding: 4px;
|
||||
}
|
||||
|
||||
.side-menu-widget-item-label {
|
||||
.side-menu-widget-item label {
|
||||
cursor: inherit;
|
||||
}
|
||||
|
||||
|
@ -360,7 +374,6 @@
|
|||
}
|
||||
|
||||
.side-menu-widget-item-other > label {
|
||||
cursor: inherit;
|
||||
color: #f5f7fa;
|
||||
text-shadow: 0 1px 1px #111;
|
||||
}
|
||||
|
@ -398,14 +411,15 @@
|
|||
-moz-margin-end: 1px;
|
||||
}
|
||||
|
||||
.variables-view-scope > .variables-view-element-details.nonenum:not(:empty) {
|
||||
border-top: 1px solid #ddd;
|
||||
.variables-view-scope > .variables-view-element-details.enum:not(:empty) {
|
||||
border-bottom: 1px solid #ddd;
|
||||
}
|
||||
|
||||
/* Generic traits applied to both variables and properties */
|
||||
|
||||
.variable-or-property {
|
||||
transition: background 1s ease-in-out;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.variable-or-property[changed] {
|
||||
|
@ -471,7 +485,6 @@
|
|||
}
|
||||
|
||||
.variable-or-property:not(:focus) > .title > .token-string {
|
||||
max-width: 30em;
|
||||
color: #1c00cf;
|
||||
}
|
||||
|
||||
|
|
|
@ -165,6 +165,7 @@ browser.jar:
|
|||
skin/classic/browser/devtools/splitview.css (devtools/splitview.css)
|
||||
skin/classic/browser/devtools/styleeditor.css (devtools/styleeditor.css)
|
||||
skin/classic/browser/devtools/debugger.css (devtools/debugger.css)
|
||||
skin/classic/browser/devtools/netmonitor.css (devtools/netmonitor.css)
|
||||
skin/classic/browser/devtools/magnifying-glass.png (devtools/magnifying-glass.png)
|
||||
skin/classic/browser/devtools/option-icon.png (devtools/option-icon.png)
|
||||
skin/classic/browser/devtools/itemToggle.png (devtools/itemToggle.png)
|
||||
|
|
|
@ -269,7 +269,7 @@
|
|||
|
||||
.devtools-sidebar-tabs > tabs > tab {
|
||||
-moz-appearance: none;
|
||||
/* We want to match the height of a toolbar with a toolbarbutton
|
||||
/* We want to match the height of a toolbar with a toolbarbutton
|
||||
* First, we need to replicated the padding of toolbar (4px),
|
||||
* then, the padding of the button itself from toolbarbutton.css (3px),
|
||||
* Also, we need to take the border of the buttons into accout (1px).
|
||||
|
|
|
@ -19,20 +19,6 @@
|
|||
-moz-border-start-color: transparent;
|
||||
}
|
||||
|
||||
/* Watch expressions, variables and other instruments pane */
|
||||
|
||||
#instruments-pane {
|
||||
min-width: 50px;
|
||||
-moz-margin-start: 0px !important;
|
||||
/* Unfortunately, transitions don't work properly with locale-aware properties,
|
||||
so both the left and right margins are set via js, while the start margin
|
||||
is always overridden here. */
|
||||
}
|
||||
|
||||
#instruments-pane[animated] {
|
||||
transition: margin 0.25s ease-in-out;
|
||||
}
|
||||
|
||||
/* ListWidget items */
|
||||
|
||||
.list-widget-item {
|
||||
|
@ -312,12 +298,12 @@
|
|||
background: none;
|
||||
box-shadow: none;
|
||||
border: none;
|
||||
list-style-image: url("chrome://browser/skin/devtools/debugger-expand.png");
|
||||
list-style-image: url("chrome://browser/skin/devtools/debugger-collapse.png");
|
||||
-moz-image-region: rect(0px,16px,16px,0px);
|
||||
}
|
||||
|
||||
#instruments-pane-toggle:not([toggled]) {
|
||||
list-style-image: url("chrome://browser/skin/devtools/debugger-collapse.png");
|
||||
#instruments-pane-toggle[pane-collapsed] {
|
||||
list-style-image: url("chrome://browser/skin/devtools/debugger-expand.png");
|
||||
}
|
||||
|
||||
#instruments-pane-toggle:active {
|
||||
|
|
|
@ -0,0 +1,304 @@
|
|||
/* vim:set ts=2 sw=2 sts=2 et: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/* Network requests table */
|
||||
|
||||
#body {
|
||||
background: url(background-noise-toolbar.png), hsl(208,11%,27%);
|
||||
}
|
||||
|
||||
.requests-menu-empty-notice {
|
||||
background: url(background-noise-toolbar.png), hsl(208,11%,27%);
|
||||
padding: 12px;
|
||||
font-size: 110%;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
#requests-menu-toolbar {
|
||||
-moz-padding-start: 4px;
|
||||
}
|
||||
|
||||
.requests-menu-header {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.requests-menu-subitem {
|
||||
padding: 0 4px;
|
||||
}
|
||||
|
||||
.requests-menu-header:not(:last-of-type),
|
||||
.requests-menu-subitem:not(:last-child) {
|
||||
-moz-border-end: 1px solid hsla(210,8%,5%,.25);
|
||||
box-shadow: 1px 0 0 hsla(210,16%,76%,.1);
|
||||
}
|
||||
|
||||
.requests-menu-status-and-method {
|
||||
width: 8em;
|
||||
}
|
||||
|
||||
.requests-menu-status {
|
||||
background: #fff;
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
-moz-margin-start: 4px;
|
||||
-moz-margin-end: 2px;
|
||||
border-radius: 20px;
|
||||
box-shadow:
|
||||
0 0 0 1px rgba(255,255,255,0.4) inset,
|
||||
0 -6px 4px 0 rgba(32,32,32,1.0) inset,
|
||||
0 0 8px 0 rgba(32,0,0,0.4);
|
||||
transition: box-shadow 0.5s ease-in-out;
|
||||
}
|
||||
|
||||
.requests-menu-status[code^="1"] {
|
||||
box-shadow:
|
||||
0 0 2px 1px rgba(255,255,255,0.8) inset,
|
||||
0 -6px 4px 0 rgba(0,0,64,1.0) inset,
|
||||
0 0 8px 0 rgba(0,0,128,1.0);
|
||||
}
|
||||
|
||||
.requests-menu-status[code^="2"] {
|
||||
box-shadow:
|
||||
0 0 2px 1px rgba(255,255,255,0.8) inset,
|
||||
0 -6px 4px 0 rgba(0,64,0,1.0) inset,
|
||||
0 0 8px 0 rgba(0,128,0,1.0);
|
||||
}
|
||||
|
||||
.requests-menu-status[code^="3"] {
|
||||
box-shadow:
|
||||
0 0 2px 1px rgba(255,255,255,0.8) inset,
|
||||
0 -6px 4px 0 rgba(64,32,0,1.0) inset,
|
||||
0 0 8px 0 rgba(128,128,0,1.0);
|
||||
}
|
||||
|
||||
.requests-menu-status[code^="4"] {
|
||||
box-shadow:
|
||||
0 0 2px 1px rgba(255,255,255,0.8) inset,
|
||||
0 -6px 4px 0 rgba(64,0,0,1.0) inset,
|
||||
0 0 8px 0 rgba(128,0,0,1.0);
|
||||
}
|
||||
|
||||
.requests-menu-status[code^="5"] {
|
||||
box-shadow:
|
||||
0 0 2px 1px rgba(255,255,255,0.8) inset,
|
||||
0 -6px 4px 0 rgba(64,0,64,1.0) inset,
|
||||
0 0 8px 0 rgba(128,0,128,1.0);
|
||||
}
|
||||
|
||||
.requests-menu-method {
|
||||
text-align: center;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.requests-menu-file {
|
||||
width: 16em;
|
||||
}
|
||||
|
||||
.requests-menu-domain {
|
||||
width: 16em;
|
||||
}
|
||||
|
||||
.requests-menu-type {
|
||||
text-align: center;
|
||||
width: 4em;
|
||||
}
|
||||
|
||||
.requests-menu-size {
|
||||
text-align: center;
|
||||
width: 8em;
|
||||
}
|
||||
|
||||
.requests-menu-header.requests-menu-waterfall {
|
||||
-moz-padding-start: 8px;
|
||||
-moz-padding-end: 8px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/* Network request waterfall */
|
||||
|
||||
.requests-menu-subitem.requests-menu-waterfall {
|
||||
-moz-padding-start: 4px;
|
||||
-moz-padding-end: 4px;
|
||||
background-size: 5px;
|
||||
background-image:
|
||||
-moz-linear-gradient(left,
|
||||
transparent 25%,
|
||||
rgba(255,255,255,0.02) 25%,
|
||||
rgba(255,255,255,0.02) 75%,
|
||||
transparent 75%);
|
||||
}
|
||||
|
||||
.requests-menu-timings {
|
||||
transform-origin: left center;
|
||||
}
|
||||
|
||||
.requests-menu-timings-total {
|
||||
-moz-padding-start: 4px;
|
||||
font-size: 85%;
|
||||
font-weight: 600;
|
||||
transform-origin: -4px center; /* negative cap size */
|
||||
}
|
||||
|
||||
.requests-menu-timings-cap {
|
||||
width: 4px;
|
||||
height: 10px;
|
||||
border: 1px solid #fff;
|
||||
}
|
||||
|
||||
.requests-menu-timings-cap.start {
|
||||
-moz-border-end: none;
|
||||
border-radius: 4px 0 0 4px;
|
||||
transform-origin: right center;
|
||||
}
|
||||
|
||||
.requests-menu-timings-cap.end {
|
||||
-moz-border-start: none;
|
||||
border-radius: 0 4px 4px 0;
|
||||
transform-origin: left center;
|
||||
}
|
||||
|
||||
.requests-menu-timings-box {
|
||||
height: 10px;
|
||||
border-top: 1px solid #fff;
|
||||
border-bottom: 1px solid #fff;
|
||||
}
|
||||
|
||||
.requests-menu-timings-box.blocked,
|
||||
.requests-menu-timings-cap.blocked {
|
||||
background-color: rgba(255,32,32,0.8);
|
||||
box-shadow: 0 0 8px 0 rgba(128,32,32,0.8),
|
||||
0 0 4px 0 rgba(255,255,255,1.0) inset;
|
||||
}
|
||||
|
||||
.requests-menu-timings-box.dns,
|
||||
.requests-menu-timings-cap.dns {
|
||||
background-color: rgba(255,128,255,0.6);
|
||||
box-shadow: 0 0 8px 0 rgba(128,128,255,1.0),
|
||||
0 0 4px 0 rgba(255,255,255,1.0) inset;
|
||||
}
|
||||
|
||||
.requests-menu-timings-box.connect,
|
||||
.requests-menu-timings-cap.connect {
|
||||
background-color: rgba(255,128,16,0.4);
|
||||
box-shadow: 0 0 8px 0 rgba(128,128,16,0.8),
|
||||
0 0 4px 0 rgba(255,255,255,1.0) inset;
|
||||
}
|
||||
|
||||
.requests-menu-timings-box.send,
|
||||
.requests-menu-timings-cap.send {
|
||||
background-color: rgba(255,255,128,0.4);
|
||||
box-shadow: 0 0 8px 0 rgba(128,255,128,0.8),
|
||||
0 0 4px 0 rgba(255,255,255,1.0) inset;
|
||||
}
|
||||
|
||||
.requests-menu-timings-box.wait,
|
||||
.requests-menu-timings-cap.wait {
|
||||
background-color: rgba(255,255,255,0.2);
|
||||
box-shadow: 0 0 8px 0 rgba(128,255,255,0.4),
|
||||
0 0 4px 0 rgba(255,255,255,1.0) inset;
|
||||
}
|
||||
|
||||
.requests-menu-timings-box.receive,
|
||||
.requests-menu-timings-cap.receive {
|
||||
background-color: rgba(255,255,255,1.0);
|
||||
box-shadow: 0 0 8px 0 rgba(128,255,255,1.0),
|
||||
0 0 4px 0 rgba(255,255,255,1.0) inset;
|
||||
}
|
||||
|
||||
.side-menu-widget-container,
|
||||
.side-menu-widget-item-or-group {
|
||||
box-shadow: none !important;
|
||||
}
|
||||
|
||||
.side-menu-widget-item:nth-child(even) {
|
||||
background: rgba(255,255,255,0.05);
|
||||
}
|
||||
|
||||
/* Network request details */
|
||||
|
||||
#details-pane {
|
||||
background: hsl(208,11%,27%);
|
||||
max-width: 500px;
|
||||
}
|
||||
|
||||
#details-pane-toggle {
|
||||
background: none;
|
||||
box-shadow: none;
|
||||
border-color: transparent;
|
||||
list-style-image: url("chrome://browser/skin/devtools/debugger-collapse.png");
|
||||
-moz-image-region: rect(0px,16px,16px,0px);
|
||||
}
|
||||
|
||||
#details-pane-toggle[pane-collapsed] {
|
||||
list-style-image: url("chrome://browser/skin/devtools/debugger-expand.png");
|
||||
}
|
||||
|
||||
#details-pane-toggle:active {
|
||||
-moz-image-region: rect(0px,32px,16px,16px);
|
||||
}
|
||||
|
||||
/* Network request details tabpanels */
|
||||
|
||||
.tabpanel-content {
|
||||
background: url(background-noise-toolbar.png), #3e4750;
|
||||
box-shadow: 0 1px 0 hsla(204,45%,98%,.05) inset;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.tabpanel-summary-container {
|
||||
padding: 1px;
|
||||
}
|
||||
|
||||
.tabpanel-summary-label {
|
||||
-moz-padding-start: 4px;
|
||||
-moz-padding-end: 3px;
|
||||
font-weight: 600;
|
||||
text-shadow: 0 1px 0 #000;
|
||||
color: hsl(210,30%,85%);
|
||||
}
|
||||
|
||||
.tabpanel-summary-value {
|
||||
-moz-padding-start: 3px;
|
||||
font-family: Menlo, Monaco, monospace;
|
||||
}
|
||||
|
||||
/* Headers tabpanel */
|
||||
|
||||
#headers-summary-status,
|
||||
#headers-summary-version {
|
||||
padding-bottom: 2px;
|
||||
}
|
||||
|
||||
#headers-summary-size {
|
||||
padding-top: 2px;
|
||||
}
|
||||
|
||||
/* Response tabpanel */
|
||||
|
||||
#response-content-image-box {
|
||||
padding-top: 10px;
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
|
||||
#response-content-image {
|
||||
background: #fff;
|
||||
border: 1px dashed GrayText;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
/* Timings tabpanel */
|
||||
|
||||
#timings-tabpanel .tabpanel-summary-label {
|
||||
width: 10em;
|
||||
}
|
||||
|
||||
#timings-tabpanel .requests-menu-timings-box {
|
||||
transition: transform 0.2s ease-out;
|
||||
min-width: 1px;
|
||||
}
|
||||
|
||||
#timings-tabpanel .requests-menu-timings-total {
|
||||
transition: transform 0.2s ease-out;
|
||||
}
|
|
@ -3,6 +3,20 @@
|
|||
* 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/. */
|
||||
|
||||
/* Generic pane helpers */
|
||||
|
||||
.generic-toggled-side-pane {
|
||||
min-width: 50px;
|
||||
-moz-margin-start: 0px !important;
|
||||
/* Unfortunately, transitions don't work properly with locale-aware properties,
|
||||
so both the left and right margins are set via js, while the start margin
|
||||
is always overridden here. */
|
||||
}
|
||||
|
||||
.generic-toggled-side-pane[animated] {
|
||||
transition: margin 0.25s ease-in-out;
|
||||
}
|
||||
|
||||
/* BreacrumbsWidget */
|
||||
|
||||
.breadcrumbs-widget-container {
|
||||
|
@ -298,7 +312,7 @@
|
|||
}
|
||||
|
||||
.side-menu-widget-item.selected {
|
||||
background: -moz-linear-gradient(hsl(206,61%,40%), hsl(206,61%,31%)) repeat-x top left;
|
||||
background: -moz-linear-gradient(hsl(206,61%,40%), hsl(206,61%,31%)) repeat-x top left !important;
|
||||
box-shadow: inset 0 1px 0 hsla(210,40%,83%,.15),
|
||||
inset 0 -1px 0 hsla(210,40%,83%,.05);
|
||||
border-top: 0;
|
||||
|
@ -330,7 +344,7 @@
|
|||
padding: 4px;
|
||||
}
|
||||
|
||||
.side-menu-widget-item-label {
|
||||
.side-menu-widget-item label {
|
||||
cursor: inherit;
|
||||
}
|
||||
|
||||
|
@ -360,7 +374,6 @@
|
|||
}
|
||||
|
||||
.side-menu-widget-item-other > label {
|
||||
cursor: inherit;
|
||||
color: #f5f7fa;
|
||||
text-shadow: 0 1px 1px #111;
|
||||
}
|
||||
|
@ -398,14 +411,15 @@
|
|||
-moz-margin-end: 1px;
|
||||
}
|
||||
|
||||
.variables-view-scope > .variables-view-element-details.nonenum:not(:empty) {
|
||||
border-top: 1px solid #ddd;
|
||||
.variables-view-scope > .variables-view-element-details.enum:not(:empty) {
|
||||
border-bottom: 1px solid #ddd;
|
||||
}
|
||||
|
||||
/* Generic traits applied to both variables and properties */
|
||||
|
||||
.variable-or-property {
|
||||
transition: background 1s ease-in-out;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.variable-or-property[changed] {
|
||||
|
@ -471,7 +485,6 @@
|
|||
}
|
||||
|
||||
.variable-or-property:not(:focus) > .title > .token-string {
|
||||
max-width: 30em;
|
||||
color: #1c00cf;
|
||||
}
|
||||
|
||||
|
|
|
@ -250,6 +250,7 @@ browser.jar:
|
|||
skin/classic/browser/devtools/splitview.css (devtools/splitview.css)
|
||||
skin/classic/browser/devtools/styleeditor.css (devtools/styleeditor.css)
|
||||
* skin/classic/browser/devtools/debugger.css (devtools/debugger.css)
|
||||
skin/classic/browser/devtools/netmonitor.css (devtools/netmonitor.css)
|
||||
skin/classic/browser/devtools/magnifying-glass.png (devtools/magnifying-glass.png)
|
||||
skin/classic/browser/devtools/option-icon.png (devtools/option-icon.png)
|
||||
skin/classic/browser/devtools/itemToggle.png (devtools/itemToggle.png)
|
||||
|
|
|
@ -276,7 +276,7 @@
|
|||
|
||||
.devtools-sidebar-tabs > tabs > tab {
|
||||
-moz-appearance: none;
|
||||
/* We want to match the height of a toolbar with a toolbarbutton
|
||||
/* We want to match the height of a toolbar with a toolbarbutton
|
||||
* First, we need to replicated the padding of toolbar (4px),
|
||||
* then, the padding of the button itself from toolbarbutton.css (3px),
|
||||
* Also, we need to take the border of the buttons into accout (1px).
|
||||
|
|
|
@ -17,20 +17,6 @@
|
|||
-moz-border-start-color: transparent;
|
||||
}
|
||||
|
||||
/* Watch expressions, variables and other instruments pane */
|
||||
|
||||
#instruments-pane {
|
||||
min-width: 50px;
|
||||
-moz-margin-start: 0px !important;
|
||||
/* Unfortunately, transitions don't work properly with locale-aware properties,
|
||||
so both the left and right margins are set via js, while the start margin
|
||||
is always overridden here. */
|
||||
}
|
||||
|
||||
#instruments-pane[animated] {
|
||||
transition: margin 0.25s ease-in-out;
|
||||
}
|
||||
|
||||
/* ListWidget items */
|
||||
|
||||
.list-widget-item {
|
||||
|
@ -311,12 +297,12 @@
|
|||
background: none;
|
||||
box-shadow: none;
|
||||
border: none;
|
||||
list-style-image: url("chrome://browser/skin/devtools/debugger-expand.png");
|
||||
list-style-image: url("chrome://browser/skin/devtools/debugger-collapse.png");
|
||||
-moz-image-region: rect(0px,16px,16px,0px);
|
||||
}
|
||||
|
||||
#instruments-pane-toggle:not([toggled]) {
|
||||
list-style-image: url("chrome://browser/skin/devtools/debugger-collapse.png");
|
||||
#instruments-pane-toggle[pane-collapsed] {
|
||||
list-style-image: url("chrome://browser/skin/devtools/debugger-expand.png");
|
||||
}
|
||||
|
||||
#instruments-pane-toggle:hover {
|
||||
|
|
|
@ -0,0 +1,304 @@
|
|||
/* vim:set ts=2 sw=2 sts=2 et: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/* Network requests table */
|
||||
|
||||
#body {
|
||||
background: url(background-noise-toolbar.png), hsl(208,11%,27%);
|
||||
}
|
||||
|
||||
.requests-menu-empty-notice {
|
||||
background: url(background-noise-toolbar.png), hsl(208,11%,27%);
|
||||
padding: 12px;
|
||||
font-size: 110%;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
#requests-menu-toolbar {
|
||||
-moz-padding-start: 4px;
|
||||
}
|
||||
|
||||
.requests-menu-header {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.requests-menu-subitem {
|
||||
padding: 0 4px;
|
||||
}
|
||||
|
||||
.requests-menu-header:not(:last-of-type),
|
||||
.requests-menu-subitem:not(:last-child) {
|
||||
-moz-border-end: 1px solid hsla(210,8%,5%,.25);
|
||||
box-shadow: 1px 0 0 hsla(210,16%,76%,.1);
|
||||
}
|
||||
|
||||
.requests-menu-status-and-method {
|
||||
width: 8em;
|
||||
}
|
||||
|
||||
.requests-menu-status {
|
||||
background: #fff;
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
-moz-margin-start: 4px;
|
||||
-moz-margin-end: 2px;
|
||||
border-radius: 20px;
|
||||
box-shadow:
|
||||
0 0 0 1px rgba(255,255,255,0.4) inset,
|
||||
0 -6px 4px 0 rgba(32,32,32,1.0) inset,
|
||||
0 0 8px 0 rgba(32,0,0,0.4);
|
||||
transition: box-shadow 0.5s ease-in-out;
|
||||
}
|
||||
|
||||
.requests-menu-status[code^="1"] {
|
||||
box-shadow:
|
||||
0 0 2px 1px rgba(255,255,255,0.8) inset,
|
||||
0 -6px 4px 0 rgba(0,0,64,1.0) inset,
|
||||
0 0 8px 0 rgba(0,0,128,1.0);
|
||||
}
|
||||
|
||||
.requests-menu-status[code^="2"] {
|
||||
box-shadow:
|
||||
0 0 2px 1px rgba(255,255,255,0.8) inset,
|
||||
0 -6px 4px 0 rgba(0,64,0,1.0) inset,
|
||||
0 0 8px 0 rgba(0,128,0,1.0);
|
||||
}
|
||||
|
||||
.requests-menu-status[code^="3"] {
|
||||
box-shadow:
|
||||
0 0 2px 1px rgba(255,255,255,0.8) inset,
|
||||
0 -6px 4px 0 rgba(64,32,0,1.0) inset,
|
||||
0 0 8px 0 rgba(128,128,0,1.0);
|
||||
}
|
||||
|
||||
.requests-menu-status[code^="4"] {
|
||||
box-shadow:
|
||||
0 0 2px 1px rgba(255,255,255,0.8) inset,
|
||||
0 -6px 4px 0 rgba(64,0,0,1.0) inset,
|
||||
0 0 8px 0 rgba(128,0,0,1.0);
|
||||
}
|
||||
|
||||
.requests-menu-status[code^="5"] {
|
||||
box-shadow:
|
||||
0 0 2px 1px rgba(255,255,255,0.8) inset,
|
||||
0 -6px 4px 0 rgba(64,0,64,1.0) inset,
|
||||
0 0 8px 0 rgba(128,0,128,1.0);
|
||||
}
|
||||
|
||||
.requests-menu-method {
|
||||
text-align: center;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.requests-menu-file {
|
||||
width: 16em;
|
||||
}
|
||||
|
||||
.requests-menu-domain {
|
||||
width: 16em;
|
||||
}
|
||||
|
||||
.requests-menu-type {
|
||||
text-align: center;
|
||||
width: 4em;
|
||||
}
|
||||
|
||||
.requests-menu-size {
|
||||
text-align: center;
|
||||
width: 8em;
|
||||
}
|
||||
|
||||
.requests-menu-header.requests-menu-waterfall {
|
||||
-moz-padding-start: 8px;
|
||||
-moz-padding-end: 8px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/* Network request waterfall */
|
||||
|
||||
.requests-menu-subitem.requests-menu-waterfall {
|
||||
-moz-padding-start: 4px;
|
||||
-moz-padding-end: 4px;
|
||||
background-size: 5px;
|
||||
background-image:
|
||||
-moz-linear-gradient(left,
|
||||
transparent 25%,
|
||||
rgba(255,255,255,0.02) 25%,
|
||||
rgba(255,255,255,0.02) 75%,
|
||||
transparent 75%);
|
||||
}
|
||||
|
||||
.requests-menu-timings {
|
||||
transform-origin: left center;
|
||||
}
|
||||
|
||||
.requests-menu-timings-total {
|
||||
-moz-padding-start: 4px;
|
||||
font-size: 85%;
|
||||
font-weight: 600;
|
||||
transform-origin: -4px center; /* negative cap size */
|
||||
}
|
||||
|
||||
.requests-menu-timings-cap {
|
||||
width: 4px;
|
||||
height: 10px;
|
||||
border: 1px solid #fff;
|
||||
}
|
||||
|
||||
.requests-menu-timings-cap.start {
|
||||
-moz-border-end: none;
|
||||
border-radius: 4px 0 0 4px;
|
||||
transform-origin: right center;
|
||||
}
|
||||
|
||||
.requests-menu-timings-cap.end {
|
||||
-moz-border-start: none;
|
||||
border-radius: 0 4px 4px 0;
|
||||
transform-origin: left center;
|
||||
}
|
||||
|
||||
.requests-menu-timings-box {
|
||||
height: 10px;
|
||||
border-top: 1px solid #fff;
|
||||
border-bottom: 1px solid #fff;
|
||||
}
|
||||
|
||||
.requests-menu-timings-box.blocked,
|
||||
.requests-menu-timings-cap.blocked {
|
||||
background-color: rgba(255,32,32,0.8);
|
||||
box-shadow: 0 0 8px 0 rgba(128,32,32,0.8),
|
||||
0 0 4px 0 rgba(255,255,255,1.0) inset;
|
||||
}
|
||||
|
||||
.requests-menu-timings-box.dns,
|
||||
.requests-menu-timings-cap.dns {
|
||||
background-color: rgba(255,128,255,0.6);
|
||||
box-shadow: 0 0 8px 0 rgba(128,128,255,1.0),
|
||||
0 0 4px 0 rgba(255,255,255,1.0) inset;
|
||||
}
|
||||
|
||||
.requests-menu-timings-box.connect,
|
||||
.requests-menu-timings-cap.connect {
|
||||
background-color: rgba(255,128,16,0.4);
|
||||
box-shadow: 0 0 8px 0 rgba(128,128,16,0.8),
|
||||
0 0 4px 0 rgba(255,255,255,1.0) inset;
|
||||
}
|
||||
|
||||
.requests-menu-timings-box.send,
|
||||
.requests-menu-timings-cap.send {
|
||||
background-color: rgba(255,255,128,0.4);
|
||||
box-shadow: 0 0 8px 0 rgba(128,255,128,0.8),
|
||||
0 0 4px 0 rgba(255,255,255,1.0) inset;
|
||||
}
|
||||
|
||||
.requests-menu-timings-box.wait,
|
||||
.requests-menu-timings-cap.wait {
|
||||
background-color: rgba(255,255,255,0.2);
|
||||
box-shadow: 0 0 8px 0 rgba(128,255,255,0.4),
|
||||
0 0 4px 0 rgba(255,255,255,1.0) inset;
|
||||
}
|
||||
|
||||
.requests-menu-timings-box.receive,
|
||||
.requests-menu-timings-cap.receive {
|
||||
background-color: rgba(255,255,255,1.0);
|
||||
box-shadow: 0 0 8px 0 rgba(128,255,255,1.0),
|
||||
0 0 4px 0 rgba(255,255,255,1.0) inset;
|
||||
}
|
||||
|
||||
.side-menu-widget-container,
|
||||
.side-menu-widget-item-or-group {
|
||||
box-shadow: none !important;
|
||||
}
|
||||
|
||||
.side-menu-widget-item:nth-child(even) {
|
||||
background: rgba(255,255,255,0.05);
|
||||
}
|
||||
|
||||
/* Network request details */
|
||||
|
||||
#details-pane {
|
||||
background: hsl(208,11%,27%);
|
||||
max-width: 500px;
|
||||
}
|
||||
|
||||
#details-pane-toggle {
|
||||
background: none;
|
||||
box-shadow: none;
|
||||
border-color: transparent;
|
||||
list-style-image: url("chrome://browser/skin/devtools/debugger-collapse.png");
|
||||
-moz-image-region: rect(0px,16px,16px,0px);
|
||||
}
|
||||
|
||||
#details-pane-toggle[pane-collapsed] {
|
||||
list-style-image: url("chrome://browser/skin/devtools/debugger-expand.png");
|
||||
}
|
||||
|
||||
#details-pane-toggle:active {
|
||||
-moz-image-region: rect(0px,32px,16px,16px);
|
||||
}
|
||||
|
||||
/* Network request details tabpanels */
|
||||
|
||||
.tabpanel-content {
|
||||
background: url(background-noise-toolbar.png), #3e4750;
|
||||
box-shadow: 0 1px 0 hsla(204,45%,98%,.05) inset;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.tabpanel-summary-container {
|
||||
padding: 1px;
|
||||
}
|
||||
|
||||
.tabpanel-summary-label {
|
||||
-moz-padding-start: 4px;
|
||||
-moz-padding-end: 3px;
|
||||
font-weight: 600;
|
||||
text-shadow: 0 1px 0 #000;
|
||||
color: hsl(210,30%,85%);
|
||||
}
|
||||
|
||||
.tabpanel-summary-value {
|
||||
-moz-padding-start: 3px;
|
||||
font-family: Menlo, Monaco, monospace;
|
||||
}
|
||||
|
||||
/* Headers tabpanel */
|
||||
|
||||
#headers-summary-status,
|
||||
#headers-summary-version {
|
||||
padding-bottom: 2px;
|
||||
}
|
||||
|
||||
#headers-summary-size {
|
||||
padding-top: 2px;
|
||||
}
|
||||
|
||||
/* Response tabpanel */
|
||||
|
||||
#response-content-image-box {
|
||||
padding-top: 10px;
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
|
||||
#response-content-image {
|
||||
background: #fff;
|
||||
border: 1px dashed GrayText;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
/* Timings tabpanel */
|
||||
|
||||
#timings-tabpanel .tabpanel-summary-label {
|
||||
width: 10em;
|
||||
}
|
||||
|
||||
#timings-tabpanel .requests-menu-timings-box {
|
||||
transition: transform 0.2s ease-out;
|
||||
min-width: 1px;
|
||||
}
|
||||
|
||||
#timings-tabpanel .requests-menu-timings-total {
|
||||
transition: transform 0.2s ease-out;
|
||||
}
|
|
@ -3,6 +3,20 @@
|
|||
* 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/. */
|
||||
|
||||
/* Generic pane helpers */
|
||||
|
||||
.generic-toggled-side-pane {
|
||||
min-width: 50px;
|
||||
-moz-margin-start: 0px !important;
|
||||
/* Unfortunately, transitions don't work properly with locale-aware properties,
|
||||
so both the left and right margins are set via js, while the start margin
|
||||
is always overridden here. */
|
||||
}
|
||||
|
||||
.generic-toggled-side-pane[animated] {
|
||||
transition: margin 0.25s ease-in-out;
|
||||
}
|
||||
|
||||
/* BreacrumbsWidget */
|
||||
|
||||
.breadcrumbs-widget-container {
|
||||
|
@ -302,7 +316,7 @@
|
|||
}
|
||||
|
||||
.side-menu-widget-item.selected {
|
||||
background: -moz-linear-gradient(hsl(206,61%,40%), hsl(206,61%,31%)) repeat-x top left;
|
||||
background: -moz-linear-gradient(hsl(206,61%,40%), hsl(206,61%,31%)) repeat-x top left !important;
|
||||
box-shadow: inset 0 1px 0 hsla(210,40%,83%,.15),
|
||||
inset 0 -1px 0 hsla(210,40%,83%,.05);
|
||||
border-top: 0;
|
||||
|
@ -334,7 +348,7 @@
|
|||
padding: 4px;
|
||||
}
|
||||
|
||||
.side-menu-widget-item-label {
|
||||
.side-menu-widget-item label {
|
||||
cursor: inherit;
|
||||
}
|
||||
|
||||
|
@ -364,9 +378,7 @@
|
|||
}
|
||||
|
||||
.side-menu-widget-item-other > label {
|
||||
cursor: inherit;
|
||||
color: #f5f7fa;
|
||||
text-shadow: 0 1px 1px #111;
|
||||
}
|
||||
|
||||
.side-menu-widget-empty-notice-container {
|
||||
|
@ -402,14 +414,15 @@
|
|||
-moz-margin-end: 1px;
|
||||
}
|
||||
|
||||
.variables-view-scope > .variables-view-element-details.nonenum:not(:empty) {
|
||||
border-top: 1px solid #ddd;
|
||||
.variables-view-scope > .variables-view-element-details.enum:not(:empty) {
|
||||
border-bottom: 1px solid #ddd;
|
||||
}
|
||||
|
||||
/* Generic traits applied to both variables and properties */
|
||||
|
||||
.variable-or-property {
|
||||
transition: background 1s ease-in-out;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.variable-or-property[changed] {
|
||||
|
@ -475,7 +488,6 @@
|
|||
}
|
||||
|
||||
.variable-or-property:not(:focus) > .title > .token-string {
|
||||
max-width: 30em;
|
||||
color: #1c00cf;
|
||||
}
|
||||
|
||||
|
|
|
@ -192,6 +192,7 @@ browser.jar:
|
|||
skin/classic/browser/devtools/splitview.css (devtools/splitview.css)
|
||||
skin/classic/browser/devtools/styleeditor.css (devtools/styleeditor.css)
|
||||
skin/classic/browser/devtools/debugger.css (devtools/debugger.css)
|
||||
skin/classic/browser/devtools/netmonitor.css (devtools/netmonitor.css)
|
||||
skin/classic/browser/devtools/magnifying-glass.png (devtools/magnifying-glass.png)
|
||||
skin/classic/browser/devtools/option-icon.png (devtools/option-icon.png)
|
||||
skin/classic/browser/devtools/itemToggle.png (devtools/itemToggle.png)
|
||||
|
@ -432,6 +433,7 @@ browser.jar:
|
|||
skin/classic/aero/browser/devtools/splitview.css (devtools/splitview.css)
|
||||
skin/classic/aero/browser/devtools/styleeditor.css (devtools/styleeditor.css)
|
||||
skin/classic/aero/browser/devtools/debugger.css (devtools/debugger.css)
|
||||
skin/classic/aero/browser/devtools/netmonitor.css (devtools/netmonitor.css)
|
||||
skin/classic/aero/browser/devtools/magnifying-glass.png (devtools/magnifying-glass.png)
|
||||
skin/classic/aero/browser/devtools/option-icon.png (devtools/option-icon.png)
|
||||
skin/classic/aero/browser/devtools/itemToggle.png (devtools/itemToggle.png)
|
||||
|
|
|
@ -87,14 +87,11 @@ this.NetworkHelper =
|
|||
*/
|
||||
convertToUnicode: function NH_convertToUnicode(aText, aCharset)
|
||||
{
|
||||
if (!aCharset) {
|
||||
return aText;
|
||||
}
|
||||
|
||||
let conv = Cc["@mozilla.org/intl/scriptableunicodeconverter"].
|
||||
createInstance(Ci.nsIScriptableUnicodeConverter);
|
||||
conv.charset = aCharset;
|
||||
|
||||
if (aCharset) {
|
||||
conv.charset = aCharset;
|
||||
}
|
||||
try {
|
||||
return conv.ConvertToUnicode(aText);
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче