зеркало из https://github.com/mozilla/gecko-dev.git
Bug 764958 - Show cached network requests in the net monitor. r=jsantell
This commit is contained in:
Родитель
0e90ef4932
Коммит
cc0aeb3f6e
|
@ -558,8 +558,10 @@ NetworkEventsHandler.prototype = {
|
|||
return;
|
||||
}
|
||||
|
||||
let { actor, startedDateTime, method, url, isXHR } = aPacket.eventActor;
|
||||
NetMonitorView.RequestsMenu.addRequest(actor, startedDateTime, method, url, isXHR);
|
||||
let { actor, startedDateTime, method, url, isXHR, fromCache } = aPacket.eventActor;
|
||||
NetMonitorView.RequestsMenu.addRequest(
|
||||
actor, startedDateTime, method, url, isXHR, fromCache
|
||||
);
|
||||
window.emit(EVENTS.NETWORK_EVENT, actor);
|
||||
},
|
||||
|
||||
|
|
|
@ -502,8 +502,10 @@ RequestsMenuView.prototype = Heritage.extend(WidgetMethods, {
|
|||
* Specifies the request's url.
|
||||
* @param boolean aIsXHR
|
||||
* True if this request was initiated via XHR.
|
||||
* @param boolean aFromCache
|
||||
* Indicates if the result came from the browser cache
|
||||
*/
|
||||
addRequest: function(aId, aStartedDateTime, aMethod, aUrl, aIsXHR) {
|
||||
addRequest: function(aId, aStartedDateTime, aMethod, aUrl, aIsXHR, aFromCache) {
|
||||
// Convert the received date/time string to a unix timestamp.
|
||||
let unixTime = Date.parse(aStartedDateTime);
|
||||
|
||||
|
@ -521,7 +523,8 @@ RequestsMenuView.prototype = Heritage.extend(WidgetMethods, {
|
|||
startedMillis: unixTime,
|
||||
method: aMethod,
|
||||
url: aUrl,
|
||||
isXHR: aIsXHR
|
||||
isXHR: aIsXHR,
|
||||
fromCache: aFromCache
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -1237,13 +1240,20 @@ RequestsMenuView.prototype = Heritage.extend(WidgetMethods, {
|
|||
break;
|
||||
case "status":
|
||||
requestItem.attachment.status = value;
|
||||
this.updateMenuView(requestItem, key, value);
|
||||
this.updateMenuView(requestItem, key, {
|
||||
status: value,
|
||||
cached: requestItem.attachment.fromCache
|
||||
});
|
||||
break;
|
||||
case "statusText":
|
||||
requestItem.attachment.statusText = value;
|
||||
this.updateMenuView(requestItem, key,
|
||||
requestItem.attachment.status + " " +
|
||||
requestItem.attachment.statusText);
|
||||
let text = (requestItem.attachment.status + " " +
|
||||
requestItem.attachment.statusText);
|
||||
if(requestItem.attachment.fromCache) {
|
||||
text += " (cached)";
|
||||
}
|
||||
|
||||
this.updateMenuView(requestItem, key, text);
|
||||
break;
|
||||
case "headersSize":
|
||||
requestItem.attachment.headersSize = value;
|
||||
|
@ -1253,8 +1263,14 @@ RequestsMenuView.prototype = Heritage.extend(WidgetMethods, {
|
|||
this.updateMenuView(requestItem, key, value);
|
||||
break;
|
||||
case "transferredSize":
|
||||
requestItem.attachment.transferredSize = value;
|
||||
this.updateMenuView(requestItem, key, value);
|
||||
if(requestItem.attachment.fromCache) {
|
||||
requestItem.attachment.transferredSize = 0;
|
||||
this.updateMenuView(requestItem, key, 'cached');
|
||||
}
|
||||
else {
|
||||
requestItem.attachment.transferredSize = value;
|
||||
this.updateMenuView(requestItem, key, value);
|
||||
}
|
||||
break;
|
||||
case "mimeType":
|
||||
requestItem.attachment.mimeType = value;
|
||||
|
@ -1278,7 +1294,9 @@ RequestsMenuView.prototype = Heritage.extend(WidgetMethods, {
|
|||
break;
|
||||
case "eventTimings":
|
||||
requestItem.attachment.eventTimings = value;
|
||||
this._createWaterfallView(requestItem, value.timings);
|
||||
this._createWaterfallView(
|
||||
requestItem, value.timings, requestItem.attachment.fromCache
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -1385,7 +1403,8 @@ RequestsMenuView.prototype = Heritage.extend(WidgetMethods, {
|
|||
}
|
||||
case "remoteAddress":
|
||||
let domain = $(".requests-menu-domain", target);
|
||||
let tooltip = domain.getAttribute("value") + " (" + aValue + ")";
|
||||
let tooltip = (domain.getAttribute("value") +
|
||||
(aValue ? " (" + aValue + ")" : ""));
|
||||
domain.setAttribute("tooltiptext", tooltip);
|
||||
break;
|
||||
case "securityState": {
|
||||
|
@ -1399,9 +1418,9 @@ RequestsMenuView.prototype = Heritage.extend(WidgetMethods, {
|
|||
}
|
||||
case "status": {
|
||||
let node = $(".requests-menu-status", target);
|
||||
node.setAttribute("code", aValue.cached ? "cached" : aValue.status);
|
||||
let codeNode = $(".requests-menu-status-code", target);
|
||||
codeNode.setAttribute("value", aValue);
|
||||
node.setAttribute("code", aValue);
|
||||
codeNode.setAttribute("value", aValue.status);
|
||||
break;
|
||||
}
|
||||
case "statusText": {
|
||||
|
@ -1419,15 +1438,22 @@ RequestsMenuView.prototype = Heritage.extend(WidgetMethods, {
|
|||
break;
|
||||
}
|
||||
case "transferredSize": {
|
||||
let node = $(".requests-menu-transferred", target);
|
||||
|
||||
let text;
|
||||
if (aValue === null) {
|
||||
text = L10N.getStr("networkMenu.sizeUnavailable");
|
||||
} else {
|
||||
}
|
||||
else if(aValue === "cached") {
|
||||
text = aValue;
|
||||
node.classList.add('theme-comment');
|
||||
}
|
||||
else {
|
||||
let kb = aValue / 1024;
|
||||
let size = L10N.numberWithDecimals(kb, CONTENT_SIZE_DECIMALS);
|
||||
text = L10N.getFormatStr("networkMenu.sizeKB", size);
|
||||
}
|
||||
let node = $(".requests-menu-transferred", target);
|
||||
|
||||
node.setAttribute("value", text);
|
||||
node.setAttribute("tooltiptext", text);
|
||||
break;
|
||||
|
@ -1472,8 +1498,10 @@ RequestsMenuView.prototype = Heritage.extend(WidgetMethods, {
|
|||
* The network request item in this container.
|
||||
* @param object aTimings
|
||||
* An object containing timing information.
|
||||
* @param boolean aFromCache
|
||||
* Indicates if the result came from the browser cache
|
||||
*/
|
||||
_createWaterfallView: function(aItem, aTimings) {
|
||||
_createWaterfallView: function(aItem, aTimings, aFromCache) {
|
||||
let { target, attachment } = aItem;
|
||||
let sections = ["dns", "connect", "send", "wait", "receive"];
|
||||
// Skipping "blocked" because it doesn't work yet.
|
||||
|
@ -1481,6 +1509,11 @@ RequestsMenuView.prototype = Heritage.extend(WidgetMethods, {
|
|||
let timingsNode = $(".requests-menu-timings", target);
|
||||
let timingsTotal = $(".requests-menu-timings-total", timingsNode);
|
||||
|
||||
if(aFromCache) {
|
||||
timingsTotal.style.display = 'none';
|
||||
return;
|
||||
}
|
||||
|
||||
// Add a set of boxes representing timing information.
|
||||
for (let key of sections) {
|
||||
let width = aTimings[key];
|
||||
|
@ -2356,7 +2389,7 @@ NetworkDetailsView.prototype = {
|
|||
}
|
||||
|
||||
if (aData.status) {
|
||||
$("#headers-summary-status-circle").setAttribute("code", aData.status);
|
||||
$("#headers-summary-status-circle").setAttribute("code", aData.fromCache ? "cached" : aData.status);
|
||||
$("#headers-summary-status-value").setAttribute("value", aData.status + " " + aData.statusText);
|
||||
$("#headers-summary-status").removeAttribute("hidden");
|
||||
} else {
|
||||
|
@ -2727,7 +2760,9 @@ NetworkDetailsView.prototype = {
|
|||
|
||||
let tabboxWidth = $("#details-pane").getAttribute("width");
|
||||
let availableWidth = tabboxWidth / 2; // Other nodes also take some space.
|
||||
let scale = Math.max(availableWidth / aResponse.totalTime, 0);
|
||||
let scale = (aResponse.totalTime > 0 ?
|
||||
Math.max(availableWidth / aResponse.totalTime, 0) :
|
||||
0);
|
||||
|
||||
$("#timings-summary-blocked .requests-menu-timings-box")
|
||||
.setAttribute("width", blocked * scale);
|
||||
|
|
|
@ -38,6 +38,7 @@ support-files =
|
|||
[browser_net_accessibility-01.js]
|
||||
[browser_net_accessibility-02.js]
|
||||
[browser_net_autoscroll.js]
|
||||
[browser_net_cached-status.js]
|
||||
[browser_net_charts-01.js]
|
||||
[browser_net_charts-02.js]
|
||||
[browser_net_charts-03.js]
|
||||
|
|
|
@ -0,0 +1,105 @@
|
|||
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
"use strict";
|
||||
|
||||
/**
|
||||
* Tests if cached requests have the correct status code
|
||||
*/
|
||||
|
||||
let test = Task.async(function*() {
|
||||
let [tab, debuggee, monitor] = yield initNetMonitor(STATUS_CODES_URL, null, true);
|
||||
info("Starting test... ");
|
||||
|
||||
let { document, L10N, NetMonitorView } = monitor.panelWin;
|
||||
let { RequestsMenu, NetworkDetails } = NetMonitorView;
|
||||
|
||||
RequestsMenu.lazyUpdate = false;
|
||||
NetworkDetails._params.lazyEmpty = false;
|
||||
|
||||
const REQUEST_DATA = [
|
||||
{
|
||||
method: 'GET',
|
||||
uri: STATUS_CODES_SJS + "?sts=ok&cached",
|
||||
details: {
|
||||
status: 200,
|
||||
statusText: 'OK',
|
||||
type: "plain",
|
||||
fullMimeType: "text/plain; charset=utf-8"
|
||||
}
|
||||
},
|
||||
{
|
||||
method: 'GET',
|
||||
uri: STATUS_CODES_SJS + "?sts=redirect&cached",
|
||||
details: {
|
||||
status: 301,
|
||||
statusText: 'Moved Permanently',
|
||||
type: "html",
|
||||
fullMimeType: "text/html; charset=utf-8"
|
||||
}
|
||||
},
|
||||
{
|
||||
method: 'GET',
|
||||
uri: 'http://example.com/redirected',
|
||||
details: {
|
||||
status: 404,
|
||||
statusText: 'Not Found',
|
||||
type: "html",
|
||||
fullMimeType: "text/html; charset=utf-8"
|
||||
}
|
||||
},
|
||||
{
|
||||
method: 'GET',
|
||||
uri: STATUS_CODES_SJS + "?sts=ok&cached",
|
||||
details: {
|
||||
status: 200,
|
||||
statusText: "OK (cached)",
|
||||
fromCache: true,
|
||||
type: "plain",
|
||||
fullMimeType: "text/plain; charset=utf-8"
|
||||
}
|
||||
},
|
||||
{
|
||||
method: 'GET',
|
||||
uri: STATUS_CODES_SJS + "?sts=redirect&cached",
|
||||
details: {
|
||||
status: 301,
|
||||
statusText: "Moved Permanently (cached)",
|
||||
fromCache: true,
|
||||
type: "html",
|
||||
fullMimeType: "text/html; charset=utf-8"
|
||||
}
|
||||
},
|
||||
{
|
||||
method: 'GET',
|
||||
uri: 'http://example.com/redirected',
|
||||
details: {
|
||||
status: 404,
|
||||
statusText: 'Not Found',
|
||||
type: "html",
|
||||
fullMimeType: "text/html; charset=utf-8"
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
info("Performing requests #1...");
|
||||
debuggee.performCachedRequests();
|
||||
yield waitForNetworkEvents(monitor, 3);
|
||||
|
||||
info("Performing requests #2...");
|
||||
debuggee.performCachedRequests();
|
||||
yield waitForNetworkEvents(monitor, 3);
|
||||
|
||||
let index = 0;
|
||||
for (let request of REQUEST_DATA) {
|
||||
let item = RequestsMenu.getItemAtIndex(index);
|
||||
|
||||
info("Verifying request #" + index);
|
||||
yield verifyRequestItemTarget(item, request.method, request.uri, request.details);
|
||||
|
||||
index++;
|
||||
}
|
||||
|
||||
yield teardown(monitor);
|
||||
finish();
|
||||
});
|
|
@ -132,7 +132,7 @@ function toggleCache(aTarget, aDisabled) {
|
|||
return reconfigureTab(aTarget, options).then(() => navigationFinished);
|
||||
}
|
||||
|
||||
function initNetMonitor(aUrl, aWindow) {
|
||||
function initNetMonitor(aUrl, aWindow, aEnableCache) {
|
||||
info("Initializing a network monitor pane.");
|
||||
|
||||
return Task.spawn(function*() {
|
||||
|
@ -144,8 +144,10 @@ function initNetMonitor(aUrl, aWindow) {
|
|||
yield target.makeRemote();
|
||||
info("Target remoted.");
|
||||
|
||||
yield toggleCache(target, true);
|
||||
info("Cache disabled when the current and all future toolboxes are open.");
|
||||
if(!aEnableCache) {
|
||||
yield toggleCache(target, true);
|
||||
info("Cache disabled when the current and all future toolboxes are open.");
|
||||
}
|
||||
|
||||
let toolbox = yield gDevTools.showToolbox(target, "netmonitor");
|
||||
info("Netork monitor pane shown successfully.");
|
||||
|
@ -268,7 +270,8 @@ function verifyRequestItemTarget(aRequestItem, aMethod, aUrl, aData = {}) {
|
|||
info("Widget index of item: " + widgetIndex);
|
||||
info("Visible index of item: " + visibleIndex);
|
||||
|
||||
let { fuzzyUrl, status, statusText, type, fullMimeType, transferred, size, time } = aData;
|
||||
let { fuzzyUrl, status, statusText, type, fullMimeType,
|
||||
transferred, size, time, fromCache } = aData;
|
||||
let { attachment, target } = aRequestItem
|
||||
|
||||
let uri = Services.io.newURI(aUrl, null, null).QueryInterface(Ci.nsIURL);
|
||||
|
@ -314,7 +317,7 @@ function verifyRequestItemTarget(aRequestItem, aMethod, aUrl, aData = {}) {
|
|||
info("Displayed status: " + value);
|
||||
info("Displayed code: " + codeValue);
|
||||
info("Tooltip status: " + tooltip);
|
||||
is(value, status, "The displayed status is correct.");
|
||||
is(value, fromCache ? "cached" : status, "The displayed status is correct.");
|
||||
is(codeValue, status, "The displayed status code is correct.");
|
||||
is(tooltip, status + " " + statusText, "The tooltip status is correct.");
|
||||
}
|
||||
|
|
|
@ -40,6 +40,15 @@
|
|||
});
|
||||
});
|
||||
}
|
||||
|
||||
function performCachedRequests() {
|
||||
get("sjs_status-codes-test-server.sjs?sts=ok&cached", function() {
|
||||
get("sjs_status-codes-test-server.sjs?sts=redirect&cached", function() {
|
||||
// Done.
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
</script>
|
||||
</body>
|
||||
|
||||
|
|
|
@ -7,7 +7,8 @@ function handleRequest(request, response) {
|
|||
response.processAsync();
|
||||
|
||||
let params = request.queryString.split("&");
|
||||
let status = params.filter((s) => s.contains("sts="))[0].split("=")[1];
|
||||
let status = params.filter(s => s.contains("sts="))[0].split("=")[1];
|
||||
let cached = params.filter(s => s === 'cached').length !== 0;
|
||||
|
||||
let timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
|
||||
timer.initWithCallback(() => {
|
||||
|
@ -29,11 +30,24 @@ function handleRequest(request, response) {
|
|||
case "500":
|
||||
response.setStatusLine(request.httpVersion, 501, "Not Implemented");
|
||||
break;
|
||||
case "ok":
|
||||
response.setStatusLine(request.httpVersion, 200, "OK");
|
||||
break;
|
||||
case "redirect":
|
||||
response.setStatusLine(request.httpVersion, 301, "Moved Permanently");
|
||||
response.setHeader("Location", "http://example.com/redirected");
|
||||
break;
|
||||
}
|
||||
|
||||
response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate");
|
||||
response.setHeader("Pragma", "no-cache");
|
||||
response.setHeader("Expires", "0");
|
||||
if(!cached) {
|
||||
response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate");
|
||||
response.setHeader("Pragma", "no-cache");
|
||||
response.setHeader("Expires", "0");
|
||||
}
|
||||
else {
|
||||
response.setHeader("Cache-Control", "no-transform,public,max-age=300,s-maxage=900");
|
||||
response.setHeader("Expires", "Thu, 01 Dec 2100 20:00:00 GMT");
|
||||
}
|
||||
|
||||
response.setHeader("Content-Type", "text/plain; charset=utf-8", false);
|
||||
response.write("Hello status code " + status + "!");
|
||||
|
|
|
@ -26,12 +26,15 @@ add_task(function() {
|
|||
|
||||
info("Checking Netmonitor contents.");
|
||||
let requestsForCss = 0;
|
||||
let attachments = [];
|
||||
for (let item of netmonitor._view.RequestsMenu) {
|
||||
if (item.attachment.url.endsWith("doc_uncached.css")) {
|
||||
requestsForCss++;
|
||||
attachments.push(item.attachment);
|
||||
}
|
||||
}
|
||||
|
||||
is(requestsForCss, 1,
|
||||
"Got one request for doc_uncached.css after Style Editor was loaded.");
|
||||
is(attachments.length, 2,
|
||||
"Got two requests for doc_uncached.css after Style Editor was loaded.");
|
||||
ok(attachments[1].fromCache,
|
||||
"Second request was loaded from browser cache");
|
||||
});
|
||||
|
|
|
@ -228,6 +228,16 @@ label.requests-menu-status-code {
|
|||
background-color: rgba(143, 161, 178, 1); /* grey */
|
||||
}
|
||||
|
||||
.theme-dark box.requests-menu-status[code="cached"] {
|
||||
border: 2px solid rgba(95, 115, 135, 1); /* dark grey */
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.theme-light box.requests-menu-status[code="cached"] {
|
||||
border: 2px solid rgba(143, 161, 178, 1); /* grey */
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.theme-dark box.requests-menu-status[code^="1"] {
|
||||
background-color: rgba(70, 175, 227, 1); /* light blue */
|
||||
}
|
||||
|
|
|
@ -1317,7 +1317,7 @@ WebConsoleActor.prototype =
|
|||
let packet = {
|
||||
from: this.actorID,
|
||||
type: "networkEvent",
|
||||
eventActor: actor.grip(),
|
||||
eventActor: actor.grip()
|
||||
};
|
||||
|
||||
this.conn.send(packet);
|
||||
|
@ -1694,6 +1694,7 @@ NetworkEventActor.prototype =
|
|||
url: this._request.url,
|
||||
method: this._request.method,
|
||||
isXHR: this._isXHR,
|
||||
fromCache: this._fromCache,
|
||||
private: this._private,
|
||||
};
|
||||
},
|
||||
|
@ -1737,6 +1738,7 @@ NetworkEventActor.prototype =
|
|||
{
|
||||
this._startedDateTime = aNetworkEvent.startedDateTime;
|
||||
this._isXHR = aNetworkEvent.isXHR;
|
||||
this._fromCache = aNetworkEvent.fromCache;
|
||||
|
||||
for (let prop of ['method', 'url', 'httpVersion', 'headersSize']) {
|
||||
this._request[prop] = aNetworkEvent[prop];
|
||||
|
@ -1862,7 +1864,7 @@ NetworkEventActor.prototype =
|
|||
return {
|
||||
from: this.actorID,
|
||||
timings: this._timings,
|
||||
totalTime: this._totalTime,
|
||||
totalTime: this._totalTime
|
||||
};
|
||||
},
|
||||
|
||||
|
@ -1972,7 +1974,7 @@ NetworkEventActor.prototype =
|
|||
from: this.actorID,
|
||||
type: "networkEventUpdate",
|
||||
updateType: "responseStart",
|
||||
response: aInfo,
|
||||
response: aInfo
|
||||
};
|
||||
|
||||
this.conn.send(packet);
|
||||
|
@ -2088,7 +2090,7 @@ NetworkEventActor.prototype =
|
|||
from: this.actorID,
|
||||
type: "networkEventUpdate",
|
||||
updateType: "eventTimings",
|
||||
totalTime: aTotal,
|
||||
totalTime: aTotal
|
||||
};
|
||||
|
||||
this.conn.send(packet);
|
||||
|
|
|
@ -353,8 +353,10 @@ NetworkResponseListener.prototype = {
|
|||
|
||||
this.receivedData = "";
|
||||
|
||||
this.httpActivity.owner.
|
||||
addResponseContent(response, this.httpActivity.discardResponseBody);
|
||||
this.httpActivity.owner.addResponseContent(
|
||||
response,
|
||||
this.httpActivity.discardResponseBody
|
||||
);
|
||||
|
||||
this._wrappedNotificationCallbacks = null;
|
||||
this.httpActivity.channel = null;
|
||||
|
@ -507,6 +509,8 @@ NetworkMonitor.prototype = {
|
|||
if (Services.appinfo.processType != Ci.nsIXULRuntime.PROCESS_TYPE_CONTENT) {
|
||||
Services.obs.addObserver(this._httpResponseExaminer,
|
||||
"http-on-examine-response", false);
|
||||
Services.obs.addObserver(this._httpResponseExaminer,
|
||||
"http-on-examine-cached-response", false);
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -526,7 +530,9 @@ NetworkMonitor.prototype = {
|
|||
// NetworkResponseListener is responsible with updating the httpActivity
|
||||
// object with the data from the new object in openResponses.
|
||||
|
||||
if (!this.owner || aTopic != "http-on-examine-response" ||
|
||||
if (!this.owner ||
|
||||
(aTopic != "http-on-examine-response" &&
|
||||
aTopic != "http-on-examine-cached-response") ||
|
||||
!(aSubject instanceof Ci.nsIHttpChannel)) {
|
||||
return;
|
||||
}
|
||||
|
@ -577,6 +583,26 @@ NetworkMonitor.prototype = {
|
|||
httpVersionMin.value;
|
||||
|
||||
this.openResponses[response.id] = response;
|
||||
|
||||
if(aTopic === "http-on-examine-cached-response") {
|
||||
// If this is a cached response, there never was a request event
|
||||
// so we need to construct one here so the frontend gets all the
|
||||
// expected events.
|
||||
let httpActivity = this._createNetworkEvent(channel, { fromCache: true });
|
||||
httpActivity.owner.addResponseStart({
|
||||
httpVersion: response.httpVersion,
|
||||
remoteAddress: "",
|
||||
remotePort: "",
|
||||
status: response.status,
|
||||
statusText: response.statusText,
|
||||
headersSize: 0,
|
||||
}, "", true);
|
||||
|
||||
// There also is never any timing events, so we can fire this
|
||||
// event with zeroed out values.
|
||||
let timings = this._setupHarTimings(httpActivity, true);
|
||||
httpActivity.owner.addEventTimings(timings.total, timings.timings);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -711,24 +737,9 @@ NetworkMonitor.prototype = {
|
|||
},
|
||||
|
||||
/**
|
||||
* Handler for ACTIVITY_SUBTYPE_REQUEST_HEADER. When a request starts the
|
||||
* headers are sent to the server. This method creates the |httpActivity|
|
||||
* object where we store the request and response information that is
|
||||
* collected through its lifetime.
|
||||
*
|
||||
* @private
|
||||
* @param nsIHttpChannel aChannel
|
||||
* @param number aTimestamp
|
||||
* @param string aExtraStringData
|
||||
* @return void
|
||||
*/
|
||||
_onRequestHeader:
|
||||
function NM__onRequestHeader(aChannel, aTimestamp, aExtraStringData)
|
||||
{
|
||||
if (!this._matchRequest(aChannel)) {
|
||||
return;
|
||||
}
|
||||
|
||||
_createNetworkEvent: function(aChannel, { timestamp, extraStringData, fromCache }) {
|
||||
let win = NetworkHelper.getWindowForRequest(aChannel);
|
||||
let httpActivity = this.createActivityObject(aChannel);
|
||||
|
||||
|
@ -738,25 +749,32 @@ NetworkMonitor.prototype = {
|
|||
aChannel.QueryInterface(Ci.nsIPrivateBrowsingChannel);
|
||||
httpActivity.private = aChannel.isChannelPrivate;
|
||||
|
||||
httpActivity.timings.REQUEST_HEADER = {
|
||||
first: aTimestamp,
|
||||
last: aTimestamp
|
||||
};
|
||||
if(timestamp) {
|
||||
httpActivity.timings.REQUEST_HEADER = {
|
||||
first: timestamp,
|
||||
last: timestamp
|
||||
};
|
||||
}
|
||||
|
||||
let httpVersionMaj = {};
|
||||
let httpVersionMin = {};
|
||||
let event = {};
|
||||
event.startedDateTime = new Date(Math.round(aTimestamp / 1000)).toISOString();
|
||||
event.headersSize = aExtraStringData.length;
|
||||
event.method = aChannel.requestMethod;
|
||||
event.url = aChannel.URI.spec;
|
||||
event.private = httpActivity.private;
|
||||
event.headersSize = 0;
|
||||
event.startedDateTime = (timestamp ? new Date(Math.round(timestamp / 1000)) : new Date()).toISOString();
|
||||
event.fromCache = fromCache;
|
||||
|
||||
if(extraStringData) {
|
||||
event.headersSize = extraStringData.length;
|
||||
}
|
||||
|
||||
// Determine if this is an XHR request.
|
||||
httpActivity.isXHR = event.isXHR =
|
||||
(aChannel.loadInfo.contentPolicyType === Ci.nsIContentPolicy.TYPE_XMLHTTPREQUEST);
|
||||
|
||||
// Determine the HTTP version.
|
||||
let httpVersionMaj = {};
|
||||
let httpVersionMin = {};
|
||||
aChannel.QueryInterface(Ci.nsIHttpChannelInternal);
|
||||
aChannel.getRequestVersion(httpVersionMaj, httpVersionMin);
|
||||
|
||||
|
@ -785,14 +803,38 @@ NetworkMonitor.prototype = {
|
|||
cookies = NetworkHelper.parseCookieHeader(cookieHeader);
|
||||
}
|
||||
|
||||
httpActivity.owner = this.owner.onNetworkEvent(event, aChannel, this);
|
||||
httpActivity.owner = this.owner.onNetworkEvent(event, aChannel);
|
||||
|
||||
this._setupResponseListener(httpActivity);
|
||||
|
||||
this.openRequests[httpActivity.id] = httpActivity;
|
||||
|
||||
httpActivity.owner.addRequestHeaders(headers, aExtraStringData);
|
||||
httpActivity.owner.addRequestHeaders(headers, extraStringData);
|
||||
httpActivity.owner.addRequestCookies(cookies);
|
||||
|
||||
this.openRequests[httpActivity.id] = httpActivity;
|
||||
return httpActivity;
|
||||
},
|
||||
|
||||
/**
|
||||
* Handler for ACTIVITY_SUBTYPE_REQUEST_HEADER. When a request starts the
|
||||
* headers are sent to the server. This method creates the |httpActivity|
|
||||
* object where we store the request and response information that is
|
||||
* collected through its lifetime.
|
||||
*
|
||||
* @private
|
||||
* @param nsIHttpChannel aChannel
|
||||
* @param number aTimestamp
|
||||
* @param string aExtraStringData
|
||||
* @return void
|
||||
*/
|
||||
_onRequestHeader:
|
||||
function NM__onRequestHeader(aChannel, aTimestamp, aExtraStringData)
|
||||
{
|
||||
if (!this._matchRequest(aChannel)) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._createNetworkEvent(aChannel, { timestamp: aTimestamp,
|
||||
extraStringData: aExtraStringData });
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -975,17 +1017,36 @@ NetworkMonitor.prototype = {
|
|||
* Update the HTTP activity object to include timing information as in the HAR
|
||||
* spec. The HTTP activity object holds the raw timing information in
|
||||
* |timings| - these are timings stored for each activity notification. The
|
||||
* HAR timing information is constructed based on these lower level data.
|
||||
* HAR timing information is constructed based on these lower level
|
||||
* data.
|
||||
*
|
||||
* @param object aHttpActivity
|
||||
* The HTTP activity object we are working with.
|
||||
* @param boolean fromCache
|
||||
* Indicates that the result was returned from the browser cache
|
||||
* @return object
|
||||
* This object holds two properties:
|
||||
* - total - the total time for all of the request and response.
|
||||
* - timings - the HAR timings object.
|
||||
*/
|
||||
_setupHarTimings: function NM__setupHarTimings(aHttpActivity)
|
||||
_setupHarTimings: function NM__setupHarTimings(aHttpActivity, fromCache)
|
||||
{
|
||||
if(fromCache) {
|
||||
// If it came from the browser cache, we have no timing
|
||||
// information and these should all be 0
|
||||
return {
|
||||
total: 0,
|
||||
timings: {
|
||||
blocked: 0,
|
||||
dns: 0,
|
||||
connect: 0,
|
||||
send: 0,
|
||||
wait: 0,
|
||||
receive: 0
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
let timings = aHttpActivity.timings;
|
||||
let harTimings = {};
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче