зеркало из https://github.com/mozilla/gecko-dev.git
Bug 573103 - Implement WebConsole Network Panel, r=dietrich, a=blocking2.0 (beta5)
This commit is contained in:
Родитель
ec21282fad
Коммит
48694b9903
|
@ -241,6 +241,15 @@ ResponseListener.prototype =
|
||||||
if (HUDService.lastFinishedRequestCallback) {
|
if (HUDService.lastFinishedRequestCallback) {
|
||||||
HUDService.lastFinishedRequestCallback(this.httpActivity);
|
HUDService.lastFinishedRequestCallback(this.httpActivity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Call update on all panels.
|
||||||
|
this.httpActivity.panels.forEach(function(weakRef) {
|
||||||
|
let panel = weakRef.get();
|
||||||
|
if (panel) {
|
||||||
|
panel.update();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this.httpActivity.response.isDone = true;
|
||||||
this.httpActivity = null;
|
this.httpActivity = null;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -457,6 +466,471 @@ var NetworkHelper =
|
||||||
|
|
||||||
// FIREBUG CODE END.
|
// FIREBUG CODE END.
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
//// Helper for creating the network panel.
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a DOMNode and sets all the attributes of aAttributes on the created
|
||||||
|
* element.
|
||||||
|
*
|
||||||
|
* @param nsIDOMDocument aDocument
|
||||||
|
* Document to create the new DOMNode.
|
||||||
|
* @param string aTag
|
||||||
|
* Name of the tag for the DOMNode.
|
||||||
|
* @param object aAttributes
|
||||||
|
* Attributes set on the created DOMNode.
|
||||||
|
*
|
||||||
|
* @returns nsIDOMNode
|
||||||
|
*/
|
||||||
|
function createElement(aDocument, aTag, aAttributes)
|
||||||
|
{
|
||||||
|
let node = aDocument.createElement(aTag);
|
||||||
|
for (var attr in aAttributes) {
|
||||||
|
node.setAttribute(attr, aAttributes[attr]);
|
||||||
|
}
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new DOMNode and appends it to aParent.
|
||||||
|
*
|
||||||
|
* @param nsIDOMNode aParent
|
||||||
|
* A parent node to append the created element.
|
||||||
|
* @param string aTag
|
||||||
|
* Name of the tag for the DOMNode.
|
||||||
|
* @param object aAttributes
|
||||||
|
* Attributes set on the created DOMNode.
|
||||||
|
*
|
||||||
|
* @returns nsIDOMNode
|
||||||
|
*/
|
||||||
|
function createAndAppendElement(aParent, aTag, aAttributes)
|
||||||
|
{
|
||||||
|
let node = createElement(aParent.ownerDocument, aTag, aAttributes);
|
||||||
|
aParent.appendChild(node);
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
//// NetworkPanel
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new NetworkPanel.
|
||||||
|
*
|
||||||
|
* @param nsIDOMNode aParent
|
||||||
|
* Parent node to append the created panel to.
|
||||||
|
* @param object aHttpActivity
|
||||||
|
* HttpActivity to display in the panel.
|
||||||
|
*/
|
||||||
|
function NetworkPanel(aParent, aHttpActivity)
|
||||||
|
{
|
||||||
|
let doc = aParent.ownerDocument;
|
||||||
|
this.httpActivity = aHttpActivity;
|
||||||
|
|
||||||
|
// Create the underlaying panel
|
||||||
|
this.panel = createElement(doc, "panel", {
|
||||||
|
label: HUDService.getStr("NetworkPanel.label"),
|
||||||
|
titlebar: "normal",
|
||||||
|
noautofocus: "true",
|
||||||
|
noautohide: "true",
|
||||||
|
close: "true"
|
||||||
|
});
|
||||||
|
|
||||||
|
// Create the browser that displays the NetworkPanel XHTML.
|
||||||
|
this.browser = createAndAppendElement(this.panel, "browser", {
|
||||||
|
src: "chrome://global/content/NetworkPanel.xhtml",
|
||||||
|
disablehistory: "true",
|
||||||
|
flex: "1"
|
||||||
|
});
|
||||||
|
|
||||||
|
// Destroy the panel when it's closed.
|
||||||
|
this.panel.addEventListener("popuphidden", function onPopupHide() {
|
||||||
|
self.panel.removeEventListener("popuphidden", onPopupHide, false);
|
||||||
|
self.panel.parentNode.removeChild(self.panel);
|
||||||
|
self.panel = null;
|
||||||
|
self.browser = null;
|
||||||
|
self.document = null;
|
||||||
|
self.httpActivity = null;
|
||||||
|
}, false);
|
||||||
|
|
||||||
|
// Set the document object and update the content once the panel is loaded.
|
||||||
|
let self = this;
|
||||||
|
this.panel.addEventListener("load", function onLoad() {
|
||||||
|
self.panel.removeEventListener("load", onLoad, true)
|
||||||
|
self.document = self.browser.contentWindow.document;
|
||||||
|
self.update();
|
||||||
|
}, true);
|
||||||
|
|
||||||
|
// Create the footer.
|
||||||
|
let footer = createElement(doc, "hbox", { align: "end" });
|
||||||
|
createAndAppendElement(footer, "spacer", { flex: 1 });
|
||||||
|
|
||||||
|
createAndAppendElement(footer, "resizer", { dir: "bottomend" });
|
||||||
|
this.panel.appendChild(footer);
|
||||||
|
|
||||||
|
aParent.appendChild(this.panel);
|
||||||
|
}
|
||||||
|
|
||||||
|
NetworkPanel.prototype =
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The current state of the output.
|
||||||
|
*/
|
||||||
|
_state: 0,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* State variables.
|
||||||
|
*/
|
||||||
|
_INIT: 0,
|
||||||
|
_DISPLAYED_REQUEST_HEADER: 1,
|
||||||
|
_DISPLAYED_REQUEST_BODY: 2,
|
||||||
|
_DISPLAYED_RESPONSE_HEADER: 3,
|
||||||
|
_TRANSITION_CLOSED: 4,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Small helper function that is nearly equal to HUDService.getFormatStr
|
||||||
|
* except that it prefixes aName with "NetworkPanel.".
|
||||||
|
*
|
||||||
|
* @param string aName
|
||||||
|
* The name of an i10n string to format. This string is prefixed with
|
||||||
|
* "NetworkPanel." before calling the HUDService.getFormatStr function.
|
||||||
|
* @param array aArray
|
||||||
|
* Values used as placeholder for the i10n string.
|
||||||
|
* @returns string
|
||||||
|
* The i10n formated string.
|
||||||
|
*/
|
||||||
|
_format: function NP_format(aName, aArray)
|
||||||
|
{
|
||||||
|
return HUDService.getFormatStr("NetworkPanel." + aName, aArray);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @returns boolean
|
||||||
|
* True if the response is an image, false otherwise.
|
||||||
|
*/
|
||||||
|
get _responseIsImage()
|
||||||
|
{
|
||||||
|
let response = this.httpActivity.response;
|
||||||
|
if (!response || !response.header || !response.header["Content-Type"]) {
|
||||||
|
let request = this.httpActivity.request;
|
||||||
|
if (request.header["Accept"] &&
|
||||||
|
request.header["Accept"].indexOf("image/") != -1) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return response.header["Content-Type"].indexOf("image/") != -1;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @returns boolean
|
||||||
|
* Returns true if the server responded that the request is already
|
||||||
|
* in the browser's cache, false otherwise.
|
||||||
|
*/
|
||||||
|
get _isResponseCached()
|
||||||
|
{
|
||||||
|
return this.httpActivity.response.status.indexOf("304") != -1;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Appends the node with id=aId by the text aValue.
|
||||||
|
*
|
||||||
|
* @param string aId
|
||||||
|
* @param string aValue
|
||||||
|
* @returns void
|
||||||
|
*/
|
||||||
|
_appendTextNode: function NP_appendTextNode(aId, aValue)
|
||||||
|
{
|
||||||
|
let textNode = this.document.createTextNode(aValue);
|
||||||
|
this.document.getElementById(aId).appendChild(textNode);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates some HTML to display the key-value pair of the aList data. The
|
||||||
|
* generated HTML is added to node with id=aParentId.
|
||||||
|
*
|
||||||
|
* @param string aParentId
|
||||||
|
* Id of the parent node to append the list to.
|
||||||
|
* @oaram object aList
|
||||||
|
* Object that holds the key-value information to display in aParentId.
|
||||||
|
* @param boolean aIgnoreCookie
|
||||||
|
* If true, the key-value named "Cookie" is not added to the list.
|
||||||
|
* @returns void
|
||||||
|
*/
|
||||||
|
_appendList: function NP_appendList(aParentId, aList, aIgnoreCookie)
|
||||||
|
{
|
||||||
|
let parent = this.document.getElementById(aParentId);
|
||||||
|
let doc = this.document;
|
||||||
|
|
||||||
|
let sortedList = {};
|
||||||
|
Object.keys(aList).sort().forEach(function(aKey) {
|
||||||
|
sortedList[aKey] = aList[aKey];
|
||||||
|
});
|
||||||
|
|
||||||
|
for (let key in sortedList) {
|
||||||
|
if (aIgnoreCookie && key == "Cookie") {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The following code creates the HTML:
|
||||||
|
*
|
||||||
|
* <span class="property-name">${line}:</span>
|
||||||
|
* <span class="property-value">${aList[line]}</span><br>
|
||||||
|
*
|
||||||
|
* and adds it to parent.
|
||||||
|
*/
|
||||||
|
let textNode = doc.createTextNode(key + ":");
|
||||||
|
let span = doc.createElement("span");
|
||||||
|
span.setAttribute("class", "property-name");
|
||||||
|
span.appendChild(textNode);
|
||||||
|
parent.appendChild(span);
|
||||||
|
|
||||||
|
textNode = doc.createTextNode(sortedList[key]);
|
||||||
|
span = doc.createElement("span");
|
||||||
|
span.setAttribute("class", "property-value");
|
||||||
|
span.appendChild(textNode);
|
||||||
|
parent.appendChild(span);
|
||||||
|
|
||||||
|
parent.appendChild(doc.createElement("br"));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Displays the node with id=aId.
|
||||||
|
*
|
||||||
|
* @param string aId
|
||||||
|
* @returns void
|
||||||
|
*/
|
||||||
|
_displayNode: function NP_displayNode(aId)
|
||||||
|
{
|
||||||
|
this.document.getElementById(aId).style.display = "block";
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the request URL, request method, the timing information when the
|
||||||
|
* request started and the request header content on the NetworkPanel.
|
||||||
|
* If the request header contains cookie data, a list of sent cookies is
|
||||||
|
* generated and a special sent cookie section is displayed + the cookie list
|
||||||
|
* added to it.
|
||||||
|
*
|
||||||
|
* @returns void
|
||||||
|
*/
|
||||||
|
_displayRequestHeader: function NP_displayRequestHeader()
|
||||||
|
{
|
||||||
|
let timing = this.httpActivity.timing;
|
||||||
|
let request = this.httpActivity.request;
|
||||||
|
|
||||||
|
this._appendTextNode("headUrl", this.httpActivity.url);
|
||||||
|
this._appendTextNode("headMethod", this.httpActivity.method);
|
||||||
|
|
||||||
|
this._appendTextNode("requestHeadersInfo",
|
||||||
|
ConsoleUtils.timestampString(timing.REQUEST_HEADER/1000));
|
||||||
|
|
||||||
|
this._appendList("requestHeadersContent", request.header, true);
|
||||||
|
|
||||||
|
if ("Cookie" in request.header) {
|
||||||
|
this._displayNode("requestCookie");
|
||||||
|
|
||||||
|
let cookies = request.header.Cookie.split(";");
|
||||||
|
let cookieList = {};
|
||||||
|
let cookieListSorted = {};
|
||||||
|
cookies.forEach(function(cookie) {
|
||||||
|
let name, value;
|
||||||
|
[name, value] = cookie.trim().split("=");
|
||||||
|
cookieList[name] = value;
|
||||||
|
});
|
||||||
|
this._appendList("requestCookieContent", cookieList);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Displays the request body section of the NetworkPanel and set the request
|
||||||
|
* body content on the NetworkPanel.
|
||||||
|
*
|
||||||
|
* @returns void
|
||||||
|
*/
|
||||||
|
_displayRequestBody: function NP_displayRequestBody() {
|
||||||
|
this._displayNode("requestBody");
|
||||||
|
this._appendTextNode("requestBodyContent", this.httpActivity.request.body);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Displays the response section of the NetworkPanel, sets the response status,
|
||||||
|
* the duration between the start of the request and the receiving of the
|
||||||
|
* response header as well as the response header content on the the NetworkPanel.
|
||||||
|
*
|
||||||
|
* @returns void
|
||||||
|
*/
|
||||||
|
_displayResponseHeader: function NP_displayResponseHeader()
|
||||||
|
{
|
||||||
|
let timing = this.httpActivity.timing;
|
||||||
|
let response = this.httpActivity.response;
|
||||||
|
|
||||||
|
this._appendTextNode("headStatus", response.status);
|
||||||
|
|
||||||
|
let deltaDuration =
|
||||||
|
Math.round((timing.RESPONSE_HEADER - timing.REQUEST_HEADER) / 1000);
|
||||||
|
this._appendTextNode("responseHeadersInfo",
|
||||||
|
this._format("durationMS", [deltaDuration]));
|
||||||
|
|
||||||
|
this._displayNode("responseContainer");
|
||||||
|
this._appendList("responseHeadersContent", response.header);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Displays the respones image section, sets the source of the image displayed
|
||||||
|
* in the image response section to the request URL and the duration between
|
||||||
|
* the receiving of the response header and the end of the request. Once the
|
||||||
|
* image is loaded, the size of the requested image is set.
|
||||||
|
*
|
||||||
|
* @returns void
|
||||||
|
*/
|
||||||
|
_displayResponseImage: function NP_displayResponseImage()
|
||||||
|
{
|
||||||
|
let self = this;
|
||||||
|
let timing = this.httpActivity.timing;
|
||||||
|
let response = this.httpActivity.response;
|
||||||
|
let cached = "";
|
||||||
|
|
||||||
|
if (this._isResponseCached) {
|
||||||
|
cached = "Cached";
|
||||||
|
}
|
||||||
|
|
||||||
|
let imageNode = this.document.getElementById("responseImage" + cached +"Node");
|
||||||
|
imageNode.setAttribute("src", this.httpActivity.url);
|
||||||
|
|
||||||
|
// This function is called to set the imageInfo.
|
||||||
|
function setImageInfo() {
|
||||||
|
let deltaDuration =
|
||||||
|
Math.round((timing.RESPONSE_COMPLETE - timing.RESPONSE_HEADER) / 1000);
|
||||||
|
self._appendTextNode("responseImage" + cached + "Info",
|
||||||
|
self._format("imageSizeDeltaDurationMS", [
|
||||||
|
imageNode.width, imageNode.height, deltaDuration
|
||||||
|
]
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the image is already loaded.
|
||||||
|
if (imageNode.width != 0) {
|
||||||
|
setImageInfo();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Image is not loaded yet therefore add a load event.
|
||||||
|
imageNode.addEventListener("load", function imageNodeLoad() {
|
||||||
|
imageNode.removeEventListener("load", imageNodeLoad, false);
|
||||||
|
setImageInfo();
|
||||||
|
}, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
this._displayNode("responseImage" + cached);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Displays the response body section, sets the the duration between
|
||||||
|
* the receiving of the response header and the end of the request as well as
|
||||||
|
* the content of the response body on the NetworkPanel.
|
||||||
|
*
|
||||||
|
* @returns void
|
||||||
|
*/
|
||||||
|
_displayResponseBody: function NP_displayResponseBody()
|
||||||
|
{
|
||||||
|
let timing = this.httpActivity.timing;
|
||||||
|
let response = this.httpActivity.response;
|
||||||
|
|
||||||
|
let deltaDuration =
|
||||||
|
Math.round((timing.RESPONSE_COMPLETE - timing.RESPONSE_HEADER) / 1000);
|
||||||
|
this._appendTextNode("responseBodyInfo",
|
||||||
|
this._format("durationMS", [deltaDuration]));
|
||||||
|
|
||||||
|
this._displayNode("responseBody");
|
||||||
|
this._appendTextNode("responseBodyContent", response.body);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Displays the `no response body` section and sets the the duration between
|
||||||
|
* the receiving of the response header and the end of the request.
|
||||||
|
*
|
||||||
|
* @returns void
|
||||||
|
*/
|
||||||
|
_displayNoResponseBody: function NP_displayNoResponseBody()
|
||||||
|
{
|
||||||
|
let timing = this.httpActivity.timing;
|
||||||
|
|
||||||
|
this._displayNode("responseNoBody");
|
||||||
|
let deltaDuration =
|
||||||
|
Math.round((timing.RESPONSE_COMPLETE - timing.RESPONSE_HEADER) / 1000);
|
||||||
|
this._appendTextNode("responseNoBodyInfo",
|
||||||
|
this._format("durationMS", [deltaDuration]));
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the content of the NetworkPanel's browser.
|
||||||
|
*
|
||||||
|
* @returns void
|
||||||
|
*/
|
||||||
|
update: function NP_update()
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* After the browser contentWindow is ready, the document object is set.
|
||||||
|
* If the document object isn't set yet, then the page is loaded and nothing
|
||||||
|
* can be updated.
|
||||||
|
*/
|
||||||
|
if (!this.document) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let timing = this.httpActivity.timing;
|
||||||
|
let request = this.httpActivity.request;
|
||||||
|
let response = this.httpActivity.response;
|
||||||
|
|
||||||
|
switch (this._state) {
|
||||||
|
case this._INIT:
|
||||||
|
this._displayRequestHeader();
|
||||||
|
this._state = this._DISPLAYED_REQUEST_HEADER;
|
||||||
|
// FALL THROUGH
|
||||||
|
|
||||||
|
case this._DISPLAYED_REQUEST_HEADER:
|
||||||
|
// Process the request body if there is one.
|
||||||
|
if (request.body) {
|
||||||
|
this._displayRequestBody();
|
||||||
|
this._state = this._DISPLAYED_REQUEST_BODY;
|
||||||
|
}
|
||||||
|
// FALL THROUGH
|
||||||
|
|
||||||
|
case this._DISPLAYED_REQUEST_BODY:
|
||||||
|
// There is always a response header. Therefore we can skip here if
|
||||||
|
// we don't have a response header yet and don't have to try updating
|
||||||
|
// anything else in the NetworkPanel.
|
||||||
|
if (!response.header) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
this._displayResponseHeader();
|
||||||
|
this._state = this._DISPLAYED_RESPONSE_HEADER;
|
||||||
|
// FALL THROUGH
|
||||||
|
|
||||||
|
case this._DISPLAYED_RESPONSE_HEADER:
|
||||||
|
// Check if the transition is done.
|
||||||
|
if (timing.TRANSACTION_CLOSE && response.isDone) {
|
||||||
|
if (this._responseIsImage) {
|
||||||
|
this._displayResponseImage();
|
||||||
|
}
|
||||||
|
else if (response.body) {
|
||||||
|
this._displayResponseBody();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this._displayNoResponseBody();
|
||||||
|
}
|
||||||
|
this._state = this._TRANSITION_CLOSED;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function HUD_SERVICE()
|
function HUD_SERVICE()
|
||||||
{
|
{
|
||||||
// TODO: provide mixins for FENNEC: bug 568621
|
// TODO: provide mixins for FENNEC: bug 568621
|
||||||
|
@ -1008,6 +1482,11 @@ HUD_SERVICE.prototype =
|
||||||
*/
|
*/
|
||||||
unregisterDisplay: function HS_unregisterDisplay(aId)
|
unregisterDisplay: function HS_unregisterDisplay(aId)
|
||||||
{
|
{
|
||||||
|
// Remove children from the output. If the output is not cleared, there can
|
||||||
|
// be leaks as some nodes has node.onclick = function; set and GC can't
|
||||||
|
// remove the nodes then.
|
||||||
|
HUDService.clearDisplay(aId);
|
||||||
|
|
||||||
// remove HUD DOM node and
|
// remove HUD DOM node and
|
||||||
// remove display references from local registries get the outputNode
|
// remove display references from local registries get the outputNode
|
||||||
var outputNode = this.mixins.getOutputNodeById(aId);
|
var outputNode = this.mixins.getOutputNodeById(aId);
|
||||||
|
@ -1366,6 +1845,28 @@ HUD_SERVICE.prototype =
|
||||||
*/
|
*/
|
||||||
lastFinishedRequestCallback: null,
|
lastFinishedRequestCallback: null,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Opens a NetworkPanel.
|
||||||
|
*
|
||||||
|
* @param nsIDOMNode aNode
|
||||||
|
* DOMNode to display the panel next to.
|
||||||
|
* @param object aHttpActivity
|
||||||
|
* httpActivity object. The data of this object is displayed in the
|
||||||
|
* NetworkPanel.
|
||||||
|
* @returns NetworkPanel
|
||||||
|
*/
|
||||||
|
openNetworkPanel: function (aNode, aHttpActivity) {
|
||||||
|
let doc = aNode.ownerDocument;
|
||||||
|
let parent = doc.getElementById("mainPopupSet");
|
||||||
|
let netPanel = new NetworkPanel(parent, aHttpActivity);
|
||||||
|
|
||||||
|
let panel = netPanel.panel;
|
||||||
|
panel.openPopup(aNode, "after_pointer", 0, 0, false, false);
|
||||||
|
panel.sizeTo(350, 400);
|
||||||
|
aHttpActivity.panels.push(Cu.getWeakReference(netPanel));
|
||||||
|
return netPanel;
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Begin observing HTTP traffic that we care about,
|
* Begin observing HTTP traffic that we care about,
|
||||||
* namely traffic that originates inside any context that a Heads Up Display
|
* namely traffic that originates inside any context that a Heads Up Display
|
||||||
|
@ -1413,6 +1914,7 @@ HUD_SERVICE.prototype =
|
||||||
method: aChannel.requestMethod,
|
method: aChannel.requestMethod,
|
||||||
channel: aChannel,
|
channel: aChannel,
|
||||||
|
|
||||||
|
panels: [],
|
||||||
request: {
|
request: {
|
||||||
header: { }
|
header: { }
|
||||||
},
|
},
|
||||||
|
@ -1450,6 +1952,13 @@ HUD_SERVICE.prototype =
|
||||||
// Store the loggedNode and the httpActivity object for later reuse.
|
// Store the loggedNode and the httpActivity object for later reuse.
|
||||||
httpActivity.messageObject = loggedNode;
|
httpActivity.messageObject = loggedNode;
|
||||||
self.openRequests[httpActivity.id] = httpActivity;
|
self.openRequests[httpActivity.id] = httpActivity;
|
||||||
|
|
||||||
|
// Make the network span clickable.
|
||||||
|
let linkNode = loggedNode.messageNode;
|
||||||
|
linkNode.setAttribute("aria-haspopup", "true");
|
||||||
|
linkNode.onclick = function() {
|
||||||
|
self.openNetworkPanel(linkNode, httpActivity);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// Iterate over all currently ongoing requests. If aChannel can't
|
// Iterate over all currently ongoing requests. If aChannel can't
|
||||||
|
@ -1467,7 +1976,7 @@ HUD_SERVICE.prototype =
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let msgObject;
|
let msgObject, updatePanel = false;
|
||||||
let data, textNode;
|
let data, textNode;
|
||||||
// Store the time information for this activity subtype.
|
// Store the time information for this activity subtype.
|
||||||
httpActivity.timing[transCodes[aActivitySubtype]] = aTimestamp;
|
httpActivity.timing[transCodes[aActivitySubtype]] = aTimestamp;
|
||||||
|
@ -1481,7 +1990,7 @@ HUD_SERVICE.prototype =
|
||||||
if (!sentBody) {
|
if (!sentBody) {
|
||||||
// If the request URL is the same as the current page url, then
|
// If the request URL is the same as the current page url, then
|
||||||
// we can try to get the posted text from the page directly.
|
// we can try to get the posted text from the page directly.
|
||||||
// This is necessary as otherwise the
|
// This check is necessary as otherwise the
|
||||||
// NetworkHelper.readPostTextFromPage
|
// NetworkHelper.readPostTextFromPage
|
||||||
// function is called for image requests as well but these
|
// function is called for image requests as well but these
|
||||||
// are not web pages and as such don't store the posted text
|
// are not web pages and as such don't store the posted text
|
||||||
|
@ -1549,8 +2058,18 @@ HUD_SERVICE.prototype =
|
||||||
self.getFormatStr("networkUrlWithStatusAndDuration", data)));
|
self.getFormatStr("networkUrlWithStatusAndDuration", data)));
|
||||||
|
|
||||||
delete self.openRequests[item.id];
|
delete self.openRequests[item.id];
|
||||||
|
updatePanel = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (updatePanel) {
|
||||||
|
httpActivity.panels.forEach(function(weakRef) {
|
||||||
|
let panel = weakRef.get();
|
||||||
|
if (panel) {
|
||||||
|
panel.update();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -0,0 +1,121 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
|
||||||
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
|
||||||
|
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd" [
|
||||||
|
<!ENTITY % webConsoleDTD SYSTEM "chrome://global/locale/webConsole.dtd" >
|
||||||
|
%webConsoleDTD;
|
||||||
|
]>
|
||||||
|
|
||||||
|
<!-- ***** BEGIN LICENSE BLOCK *****
|
||||||
|
- Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||||
|
-
|
||||||
|
- The contents of this file are subject to the Mozilla Public License Version
|
||||||
|
- 1.1 (the "License"); you may not use this file except in compliance with
|
||||||
|
- the License. You may obtain a copy of the License at
|
||||||
|
- http://www.mozilla.org/MPL/
|
||||||
|
-
|
||||||
|
- Software distributed under the License is distributed on an "AS IS" basis,
|
||||||
|
- WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||||
|
- for the specific language governing rights and limitations under the
|
||||||
|
- License.
|
||||||
|
-
|
||||||
|
- The Original Code is DevTools WebConsole Code.
|
||||||
|
-
|
||||||
|
- The Initial Developer of the Original Code is
|
||||||
|
- Mozilla Foundation.
|
||||||
|
- Portions created by the Initial Developer are Copyright (C) 2010
|
||||||
|
- the Initial Developer. All Rights Reserved.
|
||||||
|
-
|
||||||
|
- Contributor(s):
|
||||||
|
- Joe Walker <jwalker@mozilla.com>
|
||||||
|
- Julian Viereck <jviereck@mozilla.com>
|
||||||
|
-
|
||||||
|
- Alternatively, the contents of this file may be used under the terms of
|
||||||
|
- either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||||
|
- the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||||
|
- in which case the provisions of the GPL or the LGPL are applicable instead
|
||||||
|
- of those above. If you wish to allow use of your version of this file only
|
||||||
|
- under the terms of either the GPL or the LGPL, and not to allow others to
|
||||||
|
- use your version of this file under the terms of the MPL, indicate your
|
||||||
|
- decision by deleting the provisions above and replace them with the notice
|
||||||
|
- and other provisions required by the LGPL or the GPL. If you do not delete
|
||||||
|
- the provisions above, a recipient may use your version of this file under
|
||||||
|
- the terms of any one of the MPL, the GPL or the LGPL.
|
||||||
|
-
|
||||||
|
- ***** END LICENSE BLOCK ***** -->
|
||||||
|
|
||||||
|
|
||||||
|
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
|
||||||
|
<link rel="stylesheet" href="chrome://global/skin/webConsole_networkPanel.css" type="text/css"/>
|
||||||
|
</head>
|
||||||
|
<body role="application">
|
||||||
|
<div id="header">
|
||||||
|
<span class="property-name">&networkPanel.requestURL;:</span>
|
||||||
|
<span class="property-value" id="headUrl"></span><br />
|
||||||
|
<span class="property-name">&networkPanel.requestMethod;:</span>
|
||||||
|
<span class="property-value" id="headMethod"></span><br />
|
||||||
|
<span class="property-name">&networkPanel.statusCode;:</span>
|
||||||
|
<span class="property-value" id="headStatus"></span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="group">
|
||||||
|
<h1>
|
||||||
|
&networkPanel.requestHeaders;
|
||||||
|
<span id="requestHeadersInfo" class="info"></span>
|
||||||
|
</h1>
|
||||||
|
<div class="property-header" id="requestHeadersContent"></div>
|
||||||
|
|
||||||
|
<div id="requestCookie" style="display:none">
|
||||||
|
<h1>&networkPanel.requestCookie;</h1>
|
||||||
|
<div class="property-header" id="requestCookieContent"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="requestBody" style="display:none">
|
||||||
|
<h1>&networkPanel.requestBody;</h1>
|
||||||
|
<div class="property-header" id="requestBodyContent"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="group" id="responseContainer" style="display:none">
|
||||||
|
<h1>
|
||||||
|
&networkPanel.responseHeaders;
|
||||||
|
<span id="responseHeadersInfo" class="info">Δ</span>
|
||||||
|
</h1>
|
||||||
|
<div class="property-header" id="responseHeadersContent"></div>
|
||||||
|
|
||||||
|
<div id="responseBody" style="display:none">
|
||||||
|
<h1>
|
||||||
|
&networkPanel.responseBody;
|
||||||
|
<span class="info" id="responseBodyInfo">Δ</span>
|
||||||
|
</h1>
|
||||||
|
<div class="property-header" id="responseBodyContent"></div>
|
||||||
|
</div>
|
||||||
|
<div id="responseNoBody" style="display:none">
|
||||||
|
<h1>
|
||||||
|
&networkPanel.responseNoBody;
|
||||||
|
<span id="responseNoBodyInfo" class="info">Δ</span>
|
||||||
|
</h1>
|
||||||
|
</div>
|
||||||
|
<div id="responseImage" style="display:none">
|
||||||
|
<h1>
|
||||||
|
&networkPanel.responseImage;
|
||||||
|
<span id="responseImageInfo" class="info"></span>
|
||||||
|
</h1>
|
||||||
|
<div id="responseImageNodeDiv">
|
||||||
|
<img id="responseImageNode" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id="responseImageCached" style="display:none">
|
||||||
|
<h1>
|
||||||
|
&networkPanel.responseImageCached;
|
||||||
|
<span id="responseImageCachedInfo" class="info"></span>
|
||||||
|
</h1>
|
||||||
|
<div id="responseImageNodeDiv">
|
||||||
|
<img id="responseImageCachedNode" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -70,6 +70,8 @@ const TEST_ERROR_URI = "http://example.com/browser/toolkit/components/console/hu
|
||||||
|
|
||||||
const TEST_DUPLICATE_ERROR_URI = "http://example.com/browser/toolkit/components/console/hudservice/tests/browser/test-duplicate-error.html";
|
const TEST_DUPLICATE_ERROR_URI = "http://example.com/browser/toolkit/components/console/hudservice/tests/browser/test-duplicate-error.html";
|
||||||
|
|
||||||
|
const TEST_IMG = "http://example.com/browser/toolkit/components/console/hudservice/tests/browser/test-image.png";
|
||||||
|
|
||||||
function noCacheUriSpec(aUriSpec) {
|
function noCacheUriSpec(aUriSpec) {
|
||||||
return aUriSpec + "?_=" + Date.now();
|
return aUriSpec + "?_=" + Date.now();
|
||||||
}
|
}
|
||||||
|
@ -569,6 +571,254 @@ function testConsoleHistory()
|
||||||
is (input.value, executeList[idxLast], "check history next idx:" + idxLast);
|
is (input.value, executeList[idxLast], "check history next idx:" + idxLast);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function testNetworkPanel()
|
||||||
|
{
|
||||||
|
function checkIsVisible(aPanel, aList) {
|
||||||
|
for (let id in aList) {
|
||||||
|
let node = aPanel.document.getElementById(id);
|
||||||
|
let isVisible = aList[id];
|
||||||
|
is(node.style.display, (isVisible ? "block" : "none"), id + " isVisible=" + isVisible);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkNodeContent(aPanel, aId, aContent) {
|
||||||
|
let node = aPanel.document.getElementById(aId);
|
||||||
|
if (node == null) {
|
||||||
|
ok(false, "Tried to access node " + aId + " that doesn't exist!");
|
||||||
|
}
|
||||||
|
else if (node.textContent.indexOf(aContent) != -1) {
|
||||||
|
ok(true, "checking content of " + aId);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ok(false, "Got false value for " + aId + ": " + node.textContent + " doesn't have " + aContent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkNodeKeyValue(aPanel, aId, aKey, aValue) {
|
||||||
|
let node = aPanel.document.getElementById(aId);
|
||||||
|
|
||||||
|
let testHTML = '<span xmlns="http://www.w3.org/1999/xhtml" class="property-name">' + aKey + ':</span>';
|
||||||
|
testHTML += '<span xmlns="http://www.w3.org/1999/xhtml" class="property-value">' + aValue + '</span>';
|
||||||
|
isnot(node.innerHTML.indexOf(testHTML), -1, "checking content of " + aId);
|
||||||
|
}
|
||||||
|
|
||||||
|
let testDriver;
|
||||||
|
function testGen() {
|
||||||
|
var httpActivity = {
|
||||||
|
url: "http://www.testpage.com",
|
||||||
|
method: "GET",
|
||||||
|
|
||||||
|
panels: [],
|
||||||
|
request: {
|
||||||
|
header: {
|
||||||
|
foo: "bar"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
response: { },
|
||||||
|
timing: {
|
||||||
|
"REQUEST_HEADER": 0
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let networkPanel = HUDService.openNetworkPanel(filterBox, httpActivity);
|
||||||
|
|
||||||
|
is (networkPanel, httpActivity.panels[0].get(), "Network panel stored on httpActivity object");
|
||||||
|
networkPanel.panel.addEventListener("load", function onLoad() {
|
||||||
|
networkPanel.panel.removeEventListener("load", onLoad, true);
|
||||||
|
testDriver.next();
|
||||||
|
}, true);
|
||||||
|
yield;
|
||||||
|
|
||||||
|
checkIsVisible(networkPanel, {
|
||||||
|
requestCookie: false,
|
||||||
|
requestBody: false,
|
||||||
|
responseContainer: false,
|
||||||
|
responseBody: false,
|
||||||
|
responseNoBody: false,
|
||||||
|
responseImage: false,
|
||||||
|
responseImageCached: false
|
||||||
|
});
|
||||||
|
|
||||||
|
checkNodeContent(networkPanel, "header", "http://www.testpage.com");
|
||||||
|
checkNodeContent(networkPanel, "header", "GET");
|
||||||
|
checkNodeKeyValue(networkPanel, "requestHeadersContent", "foo", "bar");
|
||||||
|
|
||||||
|
// Test request body.
|
||||||
|
httpActivity.request.body = "hello world";
|
||||||
|
networkPanel.update();
|
||||||
|
checkIsVisible(networkPanel, {
|
||||||
|
requestBody: true,
|
||||||
|
requestCookie: false,
|
||||||
|
responseContainer: false,
|
||||||
|
responseBody: false,
|
||||||
|
responseNoBody: false,
|
||||||
|
responseImage: false,
|
||||||
|
responseImageCached: false
|
||||||
|
});
|
||||||
|
checkNodeContent(networkPanel, "requestBodyContent", "hello world");
|
||||||
|
|
||||||
|
// Test response header.
|
||||||
|
httpActivity.timing.RESPONSE_HEADER = 1000;
|
||||||
|
httpActivity.response.status = "999 earthquake win";
|
||||||
|
httpActivity.response.header = {
|
||||||
|
leaveHouses: "true"
|
||||||
|
}
|
||||||
|
networkPanel.update();
|
||||||
|
checkIsVisible(networkPanel, {
|
||||||
|
requestBody: true,
|
||||||
|
requestCookie: false,
|
||||||
|
responseContainer: true,
|
||||||
|
responseBody: false,
|
||||||
|
responseNoBody: false,
|
||||||
|
responseImage: false,
|
||||||
|
responseImageCached: false
|
||||||
|
});
|
||||||
|
|
||||||
|
checkNodeContent(networkPanel, "header", "999 earthquake win");
|
||||||
|
checkNodeKeyValue(networkPanel, "responseHeadersContent", "leaveHouses", "true");
|
||||||
|
checkNodeContent(networkPanel, "responseHeadersInfo", "1ms");
|
||||||
|
|
||||||
|
httpActivity.timing.RESPONSE_COMPLETE = 2500;
|
||||||
|
// This is necessary to show that the request is done.
|
||||||
|
httpActivity.timing.TRANSACTION_CLOSE = 2500;
|
||||||
|
networkPanel.update();
|
||||||
|
|
||||||
|
checkIsVisible(networkPanel, {
|
||||||
|
requestBody: true,
|
||||||
|
requestCookie: false,
|
||||||
|
responseContainer: true,
|
||||||
|
responseBody: false,
|
||||||
|
responseNoBody: false,
|
||||||
|
responseImage: false,
|
||||||
|
responseImageCached: false
|
||||||
|
});
|
||||||
|
|
||||||
|
httpActivity.response.isDone = true;
|
||||||
|
networkPanel.update();
|
||||||
|
|
||||||
|
checkNodeContent(networkPanel, "responseNoBodyInfo", "2ms");
|
||||||
|
checkIsVisible(networkPanel, {
|
||||||
|
requestBody: true,
|
||||||
|
requestCookie: false,
|
||||||
|
responseContainer: true,
|
||||||
|
responseBody: false,
|
||||||
|
responseNoBody: true,
|
||||||
|
responseImage: false,
|
||||||
|
responseImageCached: false
|
||||||
|
});
|
||||||
|
|
||||||
|
networkPanel.panel.hidePopup();
|
||||||
|
|
||||||
|
// Second run: Test for cookies and response body.
|
||||||
|
httpActivity.request.header.Cookie = "foo=bar; hello=world";
|
||||||
|
httpActivity.response.body = "get out here";
|
||||||
|
|
||||||
|
networkPanel = HUDService.openNetworkPanel(filterBox, httpActivity);
|
||||||
|
is (networkPanel, httpActivity.panels[1].get(), "Network panel stored on httpActivity object");
|
||||||
|
networkPanel.panel.addEventListener("load", function onLoad() {
|
||||||
|
networkPanel.panel.removeEventListener("load", onLoad, true);
|
||||||
|
testDriver.next();
|
||||||
|
}, true);
|
||||||
|
yield;
|
||||||
|
|
||||||
|
|
||||||
|
checkIsVisible(networkPanel, {
|
||||||
|
requestBody: true,
|
||||||
|
requestCookie: true,
|
||||||
|
responseContainer: true,
|
||||||
|
responseBody: true,
|
||||||
|
responseNoBody: false,
|
||||||
|
responseImage: false,
|
||||||
|
responseImageCached: false
|
||||||
|
});
|
||||||
|
|
||||||
|
checkNodeKeyValue(networkPanel, "requestCookieContent", "foo", "bar");
|
||||||
|
checkNodeKeyValue(networkPanel, "requestCookieContent", "hello", "world");
|
||||||
|
checkNodeContent(networkPanel, "responseBodyContent", "get out here");
|
||||||
|
checkNodeContent(networkPanel, "responseBodyInfo", "2ms");
|
||||||
|
|
||||||
|
networkPanel.panel.hidePopup();
|
||||||
|
|
||||||
|
// Check image request.
|
||||||
|
httpActivity.response.header["Content-Type"] = "image/png";
|
||||||
|
httpActivity.url = TEST_IMG;
|
||||||
|
|
||||||
|
networkPanel = HUDService.openNetworkPanel(filterBox, httpActivity);
|
||||||
|
networkPanel.panel.addEventListener("load", function onLoad() {
|
||||||
|
networkPanel.panel.removeEventListener("load", onLoad, true);
|
||||||
|
testDriver.next();
|
||||||
|
}, true);
|
||||||
|
yield;
|
||||||
|
|
||||||
|
checkIsVisible(networkPanel, {
|
||||||
|
requestBody: true,
|
||||||
|
requestCookie: true,
|
||||||
|
responseContainer: true,
|
||||||
|
responseBody: false,
|
||||||
|
responseNoBody: false,
|
||||||
|
responseImage: true,
|
||||||
|
responseImageCached: false
|
||||||
|
});
|
||||||
|
|
||||||
|
let imgNode = networkPanel.document.getElementById("responseImageNode");
|
||||||
|
is(imgNode.getAttribute("src"), TEST_IMG, "Displayed image is correct");
|
||||||
|
|
||||||
|
function checkImageResponseInfo() {
|
||||||
|
checkNodeContent(networkPanel, "responseImageInfo", "2ms");
|
||||||
|
checkNodeContent(networkPanel, "responseImageInfo", "16x16px");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the image is loaded already.
|
||||||
|
if (imgNode.width == 0) {
|
||||||
|
imgNode.addEventListener("load", function onLoad() {
|
||||||
|
imgNode.removeEventListener("load", onLoad, false);
|
||||||
|
checkImageResponseInfo();
|
||||||
|
networkPanel.panel.hidePopup();
|
||||||
|
testDriver.next();
|
||||||
|
}, false);
|
||||||
|
// Wait until the image is loaded.
|
||||||
|
yield;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
checkImageResponseInfo();
|
||||||
|
networkPanel.panel.hidePopup();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check cached image request.
|
||||||
|
httpActivity.response.status = "HTTP/1.1 304 Not Modified";
|
||||||
|
|
||||||
|
networkPanel = HUDService.openNetworkPanel(filterBox, httpActivity);
|
||||||
|
networkPanel.panel.addEventListener("load", function onLoad() {
|
||||||
|
networkPanel.panel.removeEventListener("load", onLoad, true);
|
||||||
|
testDriver.next();
|
||||||
|
}, true);
|
||||||
|
yield;
|
||||||
|
|
||||||
|
checkIsVisible(networkPanel, {
|
||||||
|
requestBody: true,
|
||||||
|
requestCookie: true,
|
||||||
|
responseContainer: true,
|
||||||
|
responseBody: false,
|
||||||
|
responseNoBody: false,
|
||||||
|
responseImage: false,
|
||||||
|
responseImageCached: true
|
||||||
|
});
|
||||||
|
|
||||||
|
let imgNode = networkPanel.document.getElementById("responseImageCachedNode");
|
||||||
|
is(imgNode.getAttribute("src"), TEST_IMG, "Displayed image is correct");
|
||||||
|
|
||||||
|
networkPanel.panel.hidePopup();
|
||||||
|
|
||||||
|
// Run the next test.
|
||||||
|
testErrorOnPageReload();
|
||||||
|
|
||||||
|
yield;
|
||||||
|
};
|
||||||
|
|
||||||
|
testDriver = testGen();
|
||||||
|
testDriver.next();
|
||||||
|
}
|
||||||
|
|
||||||
// test property provider
|
// test property provider
|
||||||
function testPropertyProvider()
|
function testPropertyProvider()
|
||||||
{
|
{
|
||||||
|
@ -829,7 +1079,7 @@ function testPageReload() {
|
||||||
is(typeof console.error, "function", "console.error is a function");
|
is(typeof console.error, "function", "console.error is a function");
|
||||||
is(typeof console.exception, "function", "console.exception is a function");
|
is(typeof console.exception, "function", "console.exception is a function");
|
||||||
|
|
||||||
testErrorOnPageReload();
|
testNetworkPanel();
|
||||||
}, false);
|
}, false);
|
||||||
|
|
||||||
content.location.reload();
|
content.location.reload();
|
||||||
|
|
|
@ -17,6 +17,8 @@ Cu.import("resource://gre/modules/HUDService.jsm");
|
||||||
|
|
||||||
const TEST_NETWORK_REQUEST_URI = "http://example.com/browser/toolkit/components/console/hudservice/tests/browser/test-network-request.html";
|
const TEST_NETWORK_REQUEST_URI = "http://example.com/browser/toolkit/components/console/hudservice/tests/browser/test-network-request.html";
|
||||||
|
|
||||||
|
const TEST_IMG = "http://example.com/browser/toolkit/components/console/hudservice/tests/browser/test-image.png";
|
||||||
|
|
||||||
const TEST_DATA_JSON_CONTENT =
|
const TEST_DATA_JSON_CONTENT =
|
||||||
'{ id: "test JSON data", myArray: [ "foo", "bar", "baz", "biff" ] }';
|
'{ id: "test JSON data", myArray: [ "foo", "bar", "baz", "biff" ] }';
|
||||||
|
|
||||||
|
@ -29,7 +31,7 @@ function testOpenWebConsole()
|
||||||
is(HUDService.displaysIndex().length, 1, "WebConsole was opened");
|
is(HUDService.displaysIndex().length, 1, "WebConsole was opened");
|
||||||
|
|
||||||
hudId = HUDService.displaysIndex()[0];
|
hudId = HUDService.displaysIndex()[0];
|
||||||
hud = HUDService.hudWeakReferences[hudId].get();
|
hud = HUDService.getHeadsUpDisplay(hudId);
|
||||||
|
|
||||||
testNetworkLogging();
|
testNetworkLogging();
|
||||||
}
|
}
|
||||||
|
@ -145,11 +147,24 @@ function testNetworkLogging()
|
||||||
|
|
||||||
lastFinishedRequest = null
|
lastFinishedRequest = null
|
||||||
|
|
||||||
// All tests are done. Shutdown.
|
// Open the NetworkPanel. The functionality of the NetworkPanel is tested
|
||||||
browser = null;
|
// within the testNetworkPanel() function.
|
||||||
lastFinishedRequest = null;
|
let filterBox = hud.querySelectorAll(".hud-filter-box")[0];
|
||||||
HUDService.lastFinishedRequestCallback = null;
|
let networkPanel = HUDService.openNetworkPanel(filterBox, httpActivity);
|
||||||
finishTest();
|
is (networkPanel, httpActivity.panels[0].get(), "Network panel stored on httpActivity object");
|
||||||
|
networkPanel.panel.addEventListener("load", function onLoad() {
|
||||||
|
networkPanel.panel.removeEventListener("load", onLoad, true);
|
||||||
|
|
||||||
|
ok(true, "NetworkPanel was opened");
|
||||||
|
networkPanel.panel.hidePopup();
|
||||||
|
|
||||||
|
// All tests are done. Shutdown.
|
||||||
|
browser = null;
|
||||||
|
lastFinishedRequest = null;
|
||||||
|
HUDService.lastFinishedRequestCallback = null;
|
||||||
|
|
||||||
|
finishTest();
|
||||||
|
}, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
loggingGen = loggingGeneratorFunc();
|
loggingGen = loggingGeneratorFunc();
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
toolkit.jar:
|
toolkit.jar:
|
||||||
*+ content/global/console.js (content/console.js)
|
*+ content/global/console.js (content/console.js)
|
||||||
*+ content/global/console.xul (content/console.xul)
|
*+ content/global/console.xul (content/console.xul)
|
||||||
|
+ content/global/NetworkPanel.xhtml (hudservice/NetworkPanel.xhtml)
|
||||||
+ content/global/console.css (content/console.css)
|
+ content/global/console.css (content/console.css)
|
||||||
+ content/global/consoleBindings.xml (content/consoleBindings.xml)
|
+ content/global/consoleBindings.xml (content/consoleBindings.xml)
|
||||||
|
|
|
@ -84,3 +84,18 @@ networkUrlWithStatus=%1$S [%2$S
|
||||||
# %2$S = response status code from the server (e.g. `HTTP/1.1 200 OK`)
|
# %2$S = response status code from the server (e.g. `HTTP/1.1 200 OK`)
|
||||||
# %3$S = duration for the complete network request in milliseconds
|
# %3$S = duration for the complete network request in milliseconds
|
||||||
networkUrlWithStatusAndDuration=%1$S [%2$S %3$Sms]
|
networkUrlWithStatusAndDuration=%1$S [%2$S %3$Sms]
|
||||||
|
NetworkPanel.label=Inspect Network Request
|
||||||
|
# LOCALIZATION NOTE (NetworkPanel.deltaDurationMS):
|
||||||
|
#
|
||||||
|
# This string is used to show the duration between two network events (e.g
|
||||||
|
# request and respones header or response header and response body).
|
||||||
|
NetworkPanel.durationMS=%Sms
|
||||||
|
# LOCALIZATION NOTE (NetworkPanel.imageSizeDeltaDurationMS):
|
||||||
|
# This string is used to show the duration between the response header and the
|
||||||
|
# response body event. It also shows the size of the received or cached image.
|
||||||
|
#
|
||||||
|
# The first %S is replace by the width of the inspected image.
|
||||||
|
# The second %S is replaced by the height of the inspected image.
|
||||||
|
# The third %S is replaced by the duration between the response header and the
|
||||||
|
# response body event.
|
||||||
|
NetworkPanel.imageSizeDeltaDurationMS=%Sx%Spx, Δ%Sms
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
<!ENTITY networkPanel.requestURL "Request URL">
|
||||||
|
<!ENTITY networkPanel.requestMethod "Request Method">
|
||||||
|
<!ENTITY networkPanel.statusCode "Status Code">
|
||||||
|
|
||||||
|
<!ENTITY networkPanel.requestHeaders "Request Headers">
|
||||||
|
<!ENTITY networkPanel.requestCookie "Sent Cookie">
|
||||||
|
<!ENTITY networkPanel.requestBody "Request Body">
|
||||||
|
<!ENTITY networkPanel.responseHeaders "Response Headers">
|
||||||
|
<!ENTITY networkPanel.responseBody "Response Body">
|
||||||
|
<!ENTITY networkPanel.responseNoBody "No Response Body">
|
||||||
|
<!ENTITY networkPanel.responseImage "Received Image">
|
||||||
|
<!ENTITY networkPanel.responseImageCached "Cached Image">
|
|
@ -37,6 +37,7 @@
|
||||||
+ locale/@AB_CD@/global/finddialog.properties (%chrome/global/finddialog.properties)
|
+ locale/@AB_CD@/global/finddialog.properties (%chrome/global/finddialog.properties)
|
||||||
locale/@AB_CD@/global/globalKeys.dtd (%chrome/global/globalKeys.dtd)
|
locale/@AB_CD@/global/globalKeys.dtd (%chrome/global/globalKeys.dtd)
|
||||||
+ locale/@AB_CD@/global/headsUpDisplay.properties (%chrome/global/headsUpDisplay.properties)
|
+ locale/@AB_CD@/global/headsUpDisplay.properties (%chrome/global/headsUpDisplay.properties)
|
||||||
|
+ locale/@AB_CD@/global/webConsole.dtd (%chrome/global/webConsole.dtd)
|
||||||
+ locale/@AB_CD@/global/intl.css (%chrome/global/intl.css)
|
+ locale/@AB_CD@/global/intl.css (%chrome/global/intl.css)
|
||||||
+ locale/@AB_CD@/global/intl.properties (%chrome/global/intl.properties)
|
+ locale/@AB_CD@/global/intl.properties (%chrome/global/intl.properties)
|
||||||
+ locale/@AB_CD@/global/keys.properties (%chrome/global/keys.properties)
|
+ locale/@AB_CD@/global/keys.properties (%chrome/global/keys.properties)
|
||||||
|
|
|
@ -28,6 +28,7 @@ toolkit.jar:
|
||||||
+ skin/classic/global/toolbarbutton.css
|
+ skin/classic/global/toolbarbutton.css
|
||||||
+ skin/classic/global/tree.css
|
+ skin/classic/global/tree.css
|
||||||
+ skin/classic/global/webConsole.css
|
+ skin/classic/global/webConsole.css
|
||||||
|
+ skin/classic/global/webConsole_networkPanel.css
|
||||||
+ skin/classic/global/alerts/alert.css (alerts/alert.css)
|
+ skin/classic/global/alerts/alert.css (alerts/alert.css)
|
||||||
+ skin/classic/global/console/console.css (console/console.css)
|
+ skin/classic/global/console/console.css (console/console.css)
|
||||||
+ skin/classic/global/console/console.png (console/console.png)
|
+ skin/classic/global/console/console.png (console/console.png)
|
||||||
|
|
|
@ -0,0 +1,108 @@
|
||||||
|
/* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the Mozilla Public License Version
|
||||||
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
* http://www.mozilla.org/MPL/
|
||||||
|
*
|
||||||
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||||
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||||
|
* for the specific language governing rights and limitations under the
|
||||||
|
* License.
|
||||||
|
*
|
||||||
|
* The Original Code is DevTools code
|
||||||
|
*
|
||||||
|
* The Initial Developer of the Original Code is
|
||||||
|
* Mozilla Corporation
|
||||||
|
* Portions created by the Initial Developer are Copyright (C) 2010
|
||||||
|
* the Initial Developer. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Contributor(s):
|
||||||
|
* Joe Walker <jwalker@mozilla.com>
|
||||||
|
* Julian Viereck <jviereck@mozilla.com>
|
||||||
|
*
|
||||||
|
* Alternatively, the contents of this file may be used under the terms of
|
||||||
|
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||||
|
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||||
|
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||||
|
* of those above. If you wish to allow use of your version of this file only
|
||||||
|
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||||
|
* use your version of this file under the terms of the MPL, indicate your
|
||||||
|
* decision by deleting the provisions above and replace them with the notice
|
||||||
|
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||||
|
* the provisions above, a recipient may use your version of this file under
|
||||||
|
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||||
|
*
|
||||||
|
* ***** END LICENSE BLOCK ***** */
|
||||||
|
|
||||||
|
body {
|
||||||
|
font-family: Lucida Grande, sans-serif;
|
||||||
|
font-size: 11px;
|
||||||
|
background: #EEE;
|
||||||
|
}
|
||||||
|
|
||||||
|
div#header {
|
||||||
|
padding: 5px;
|
||||||
|
overflow-x:auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 13px;
|
||||||
|
padding: 2px 10px;
|
||||||
|
margin: 0px;
|
||||||
|
background: -moz-linear-gradient(top, #BBB, #999);
|
||||||
|
-moz-border-radius: 2px;
|
||||||
|
text-shadow: #FFF 0px 1px 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 .info {
|
||||||
|
font-size: 11px;
|
||||||
|
float: right;
|
||||||
|
color: #333;
|
||||||
|
padding-right: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.property-header {
|
||||||
|
padding: 2px 5px;
|
||||||
|
background: -moz-linear-gradient(top, #FFF, #F8F8F8);
|
||||||
|
color: #333;
|
||||||
|
max-height: 330px;
|
||||||
|
overflow-y: auto;
|
||||||
|
overflow-x: auto;
|
||||||
|
white-space: pre-wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
span.property-name {
|
||||||
|
font-size: 11px;
|
||||||
|
font-weight: bold;
|
||||||
|
padding-right: 4px;
|
||||||
|
color: #000;
|
||||||
|
}
|
||||||
|
|
||||||
|
span.property-value {
|
||||||
|
padding-right: 5px;
|
||||||
|
font-size: 11px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.group {
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.group, div#header {
|
||||||
|
background: #FFF;
|
||||||
|
border-color: #E1E1E1;
|
||||||
|
border-style: solid;
|
||||||
|
border-width: 1px;
|
||||||
|
-moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
|
||||||
|
-moz-border-radius: 4px 4px 4px 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
img#responseImageNode {
|
||||||
|
-moz-box-shadow: rgba(0,0,0,0.2) 0px 3px 5px;
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#responseImageNodeDiv {
|
||||||
|
padding: 5px;
|
||||||
|
}
|
|
@ -50,6 +50,7 @@ toolkit.jar:
|
||||||
skin/classic/global/tree.css
|
skin/classic/global/tree.css
|
||||||
* skin/classic/global/viewbuttons.css
|
* skin/classic/global/viewbuttons.css
|
||||||
* skin/classic/global/webConsole.css
|
* skin/classic/global/webConsole.css
|
||||||
|
* skin/classic/global/webConsole_networkPanel.css
|
||||||
skin/classic/global/wizard.css
|
skin/classic/global/wizard.css
|
||||||
skin/classic/global/arrow/arrow-dn-dis.gif (arrow/arrow-dn-dis.gif)
|
skin/classic/global/arrow/arrow-dn-dis.gif (arrow/arrow-dn-dis.gif)
|
||||||
skin/classic/global/arrow/arrow-dn-dis.png (arrow/arrow-dn-dis.png)
|
skin/classic/global/arrow/arrow-dn-dis.png (arrow/arrow-dn-dis.png)
|
||||||
|
|
|
@ -0,0 +1,108 @@
|
||||||
|
/* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the Mozilla Public License Version
|
||||||
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
* http://www.mozilla.org/MPL/
|
||||||
|
*
|
||||||
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||||
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||||
|
* for the specific language governing rights and limitations under the
|
||||||
|
* License.
|
||||||
|
*
|
||||||
|
* The Original Code is DevTools code
|
||||||
|
*
|
||||||
|
* The Initial Developer of the Original Code is
|
||||||
|
* Mozilla Corporation
|
||||||
|
* Portions created by the Initial Developer are Copyright (C) 2010
|
||||||
|
* the Initial Developer. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Contributor(s):
|
||||||
|
* Joe Walker <jwalker@mozilla.com>
|
||||||
|
* Julian Viereck <jviereck@mozilla.com>
|
||||||
|
*
|
||||||
|
* Alternatively, the contents of this file may be used under the terms of
|
||||||
|
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||||
|
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||||
|
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||||
|
* of those above. If you wish to allow use of your version of this file only
|
||||||
|
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||||
|
* use your version of this file under the terms of the MPL, indicate your
|
||||||
|
* decision by deleting the provisions above and replace them with the notice
|
||||||
|
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||||
|
* the provisions above, a recipient may use your version of this file under
|
||||||
|
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||||
|
*
|
||||||
|
* ***** END LICENSE BLOCK ***** */
|
||||||
|
|
||||||
|
body {
|
||||||
|
font-family: Lucida Grande, sans-serif;
|
||||||
|
font-size: 11px;
|
||||||
|
background: #EEE;
|
||||||
|
}
|
||||||
|
|
||||||
|
div#header {
|
||||||
|
padding: 5px;
|
||||||
|
overflow-x:auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 13px;
|
||||||
|
padding: 2px 10px;
|
||||||
|
margin: 0px;
|
||||||
|
background: -moz-linear-gradient(top, #BBB, #999);
|
||||||
|
-moz-border-radius: 2px;
|
||||||
|
text-shadow: #FFF 0px 1px 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 .info {
|
||||||
|
font-size: 11px;
|
||||||
|
float: right;
|
||||||
|
color: #333;
|
||||||
|
padding-right: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.property-header {
|
||||||
|
padding: 2px 5px;
|
||||||
|
background: -moz-linear-gradient(top, #FFF, #F8F8F8);
|
||||||
|
color: #333;
|
||||||
|
max-height: 330px;
|
||||||
|
overflow-y: auto;
|
||||||
|
overflow-x: auto;
|
||||||
|
white-space: pre-wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
span.property-name {
|
||||||
|
font-size: 11px;
|
||||||
|
font-weight: bold;
|
||||||
|
padding-right: 4px;
|
||||||
|
color: #000;
|
||||||
|
}
|
||||||
|
|
||||||
|
span.property-value {
|
||||||
|
padding-right: 5px;
|
||||||
|
font-size: 11px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.group {
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.group, div#header {
|
||||||
|
background: #FFF;
|
||||||
|
border-color: #E1E1E1;
|
||||||
|
border-style: solid;
|
||||||
|
border-width: 1px;
|
||||||
|
-moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
|
||||||
|
-moz-border-radius: 4px 4px 4px 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
img#responseImageNode {
|
||||||
|
-moz-box-shadow: rgba(0,0,0,0.2) 0px 3px 5px;
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#responseImageNodeDiv {
|
||||||
|
padding: 5px;
|
||||||
|
}
|
|
@ -54,6 +54,7 @@ toolkit.jar:
|
||||||
skin/classic/global/toolbarbutton.css
|
skin/classic/global/toolbarbutton.css
|
||||||
skin/classic/global/tree.css
|
skin/classic/global/tree.css
|
||||||
* skin/classic/global/webConsole.css
|
* skin/classic/global/webConsole.css
|
||||||
|
* skin/classic/global/webConsole_networkPanel.css
|
||||||
skin/classic/global/wizard.css
|
skin/classic/global/wizard.css
|
||||||
skin/classic/global/alerts/alert.css (alerts/alert.css)
|
skin/classic/global/alerts/alert.css (alerts/alert.css)
|
||||||
skin/classic/global/arrow/arrow-dn.gif (arrow/arrow-dn.gif)
|
skin/classic/global/arrow/arrow-dn.gif (arrow/arrow-dn.gif)
|
||||||
|
@ -222,6 +223,7 @@ toolkit.jar:
|
||||||
* skin/classic/aero/global/toolbarbutton.css (toolbarbutton-aero.css)
|
* skin/classic/aero/global/toolbarbutton.css (toolbarbutton-aero.css)
|
||||||
* skin/classic/aero/global/tree.css (tree-aero.css)
|
* skin/classic/aero/global/tree.css (tree-aero.css)
|
||||||
* skin/classic/aero/global/webConsole.css
|
* skin/classic/aero/global/webConsole.css
|
||||||
|
* skin/classic/global/webConsole_networkPanel.css
|
||||||
skin/classic/aero/global/wizard.css
|
skin/classic/aero/global/wizard.css
|
||||||
skin/classic/aero/global/alerts/alert.css (alerts/alert.css)
|
skin/classic/aero/global/alerts/alert.css (alerts/alert.css)
|
||||||
skin/classic/aero/global/arrow/arrow-dn.gif (arrow/arrow-dn.gif)
|
skin/classic/aero/global/arrow/arrow-dn.gif (arrow/arrow-dn.gif)
|
||||||
|
|
|
@ -0,0 +1,108 @@
|
||||||
|
/* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the Mozilla Public License Version
|
||||||
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
* http://www.mozilla.org/MPL/
|
||||||
|
*
|
||||||
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||||
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||||
|
* for the specific language governing rights and limitations under the
|
||||||
|
* License.
|
||||||
|
*
|
||||||
|
* The Original Code is DevTools code
|
||||||
|
*
|
||||||
|
* The Initial Developer of the Original Code is
|
||||||
|
* Mozilla Corporation
|
||||||
|
* Portions created by the Initial Developer are Copyright (C) 2010
|
||||||
|
* the Initial Developer. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Contributor(s):
|
||||||
|
* Joe Walker <jwalker@mozilla.com>
|
||||||
|
* Julian Viereck <jviereck@mozilla.com>
|
||||||
|
*
|
||||||
|
* Alternatively, the contents of this file may be used under the terms of
|
||||||
|
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||||
|
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||||
|
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||||
|
* of those above. If you wish to allow use of your version of this file only
|
||||||
|
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||||
|
* use your version of this file under the terms of the MPL, indicate your
|
||||||
|
* decision by deleting the provisions above and replace them with the notice
|
||||||
|
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||||
|
* the provisions above, a recipient may use your version of this file under
|
||||||
|
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||||
|
*
|
||||||
|
* ***** END LICENSE BLOCK ***** */
|
||||||
|
|
||||||
|
body {
|
||||||
|
font-family: Lucida Grande, sans-serif;
|
||||||
|
font-size: 11px;
|
||||||
|
background: #EEE;
|
||||||
|
}
|
||||||
|
|
||||||
|
div#header {
|
||||||
|
padding: 5px;
|
||||||
|
overflow-x:auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 13px;
|
||||||
|
padding: 2px 10px;
|
||||||
|
margin: 0px;
|
||||||
|
background: -moz-linear-gradient(top, #BBB, #999);
|
||||||
|
-moz-border-radius: 2px;
|
||||||
|
text-shadow: #FFF 0px 1px 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 .info {
|
||||||
|
font-size: 11px;
|
||||||
|
float: right;
|
||||||
|
color: #333;
|
||||||
|
padding-right: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.property-header {
|
||||||
|
padding: 2px 5px;
|
||||||
|
background: -moz-linear-gradient(top, #FFF, #F8F8F8);
|
||||||
|
color: #333;
|
||||||
|
max-height: 330px;
|
||||||
|
overflow-y: auto;
|
||||||
|
overflow-x: auto;
|
||||||
|
white-space: pre-wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
span.property-name {
|
||||||
|
font-size: 11px;
|
||||||
|
font-weight: bold;
|
||||||
|
padding-right: 4px;
|
||||||
|
color: #000;
|
||||||
|
}
|
||||||
|
|
||||||
|
span.property-value {
|
||||||
|
padding-right: 5px;
|
||||||
|
font-size: 11px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.group {
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.group, div#header {
|
||||||
|
background: #FFF;
|
||||||
|
border-color: #E1E1E1;
|
||||||
|
border-style: solid;
|
||||||
|
border-width: 1px;
|
||||||
|
-moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
|
||||||
|
-moz-border-radius: 4px 4px 4px 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
img#responseImageNode {
|
||||||
|
-moz-box-shadow: rgba(0,0,0,0.2) 0px 3px 5px;
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#responseImageNodeDiv {
|
||||||
|
padding: 5px;
|
||||||
|
}
|
Загрузка…
Ссылка в новой задаче