Bug 1441761 - Properly export total time; r=ochameau
MozReview-Commit-ID: EWt41uX4xDN
--- a/devtools/client/netmonitor/src/har/har-builder.js
+++ b/devtools/client/netmonitor/src/har/har-builder.js
@@ -10,16 +10,19 @@ const { LocalizationHelper } = require("
const { CurlUtils } = require("devtools/client/shared/curl");
const {
getFormDataSections,
getUrlQuery,
parseQueryString,
} = require("../utils/request-utils");
const { buildHarLog } = require("./har-builder-utils");
const L10N = new LocalizationHelper("devtools/client/locales/har.properties");
+const {
+ TIMING_KEYS
+} = require("../constants");
/**
* This object is responsible for building HAR file. See HAR spec:
* https://dvcs.w3.org/hg/webperf/raw-file/tip/specs/HAR/Overview.html
* http://www.softwareishard.com/blog/har-12-spec/
*
* @param {Object} options configuration object
*
@@ -96,28 +99,40 @@ HarBuilder.prototype = {
},
buildEntry: async function (log, file) {
let page = this.getPage(log, file);
let entry = {};
entry.pageref = page.id;
entry.startedDateTime = dateToJSON(new Date(file.startedMillis));
- entry.time = file.endedMillis - file.startedMillis;
let eventTimings = file.eventTimings;
if (!eventTimings && this._options.requestData) {
eventTimings = await this._options.requestData(file.id, "eventTimings");
}
entry.request = await this.buildRequest(file);
entry.response = await this.buildResponse(file);
entry.cache = this.buildCache(file);
entry.timings = eventTimings ? eventTimings.timings : {};
+ // Calculate total time by summing all timings. Note that
+ // `file.totalTime` can't be used since it doesn't have to
+ // correspond to plain summary of individual timings.
+ // With TCP Fast Open and TLS early data sending data can
+ // start at the same time as connect (we can send data on
+ // TCP syn packet). Also TLS handshake can carry application
+ // data thereby overlapping a sending data period and TLS
+ // handshake period.
+ entry.time = TIMING_KEYS.reduce((sum, type) => {
+ let time = entry.timings[type];
+ return (typeof time != "undefined") ? (sum + time) : sum;
+ }, 0);
+
// Security state isn't part of HAR spec, and so create
// custom field that needs to use '_' prefix.
entry._securityState = file.securityState;
if (file.remoteAddress) {
entry.serverIPAddress = file.remoteAddress;
}
--- a/devtools/client/netmonitor/src/har/har-collector.js
+++ b/devtools/client/netmonitor/src/har/har-collector.js
@@ -378,20 +378,17 @@ HarCollector.prototype = {
* Handles additional information received for a "eventTimings" packet.
*
* @param object response
* The message received from the server.
*/
onEventTimings: function (response) {
let file = this.getFile(response.from);
file.eventTimings = response;
-
- let totalTime = response.totalTime;
- file.totalTime = totalTime;
- file.endedMillis = file.startedMillis + totalTime;
+ file.totalTime = response.totalTime;
},
// Helpers
getLongHeaders: function (headers) {
for (let header of headers) {
if (typeof header.value == "object") {
try {
--- a/devtools/client/netmonitor/src/har/test/browser_net_har_copy_all_as_har.js
+++ b/devtools/client/netmonitor/src/har/test/browser_net_har_copy_all_as_har.js
@@ -42,16 +42,17 @@ add_task(async function () {
is(har.log.pages.length, 1, "There must be one page");
is(har.log.entries.length, 1, "There must be one request");
let page = har.log.pages[0];
ok("onContentLoad" in page.pageTimings, "There must be onContentLoad time");
ok("onLoad" in page.pageTimings, "There must be onLoad time");
let entry = har.log.entries[0];
+ ok(entry.time > 0, "Check the total time");
is(entry.request.method, "GET", "Check the method");
is(entry.request.url, SIMPLE_URL, "Check the URL");
is(entry.request.headers.length, 9, "Check number of request headers");
is(entry.response.status, 200, "Check response status");
is(entry.response.statusText, "OK", "Check response status text");
is(entry.response.headers.length, 6, "Check number of response headers");
is(entry.response.content.mimeType, // eslint-disable-line
"text/html", "Check response content type"); // eslint-disable-line