Bug 1404917 - Fetch responceContent for HAR lazily. r=Honza
MozReview-Commit-ID: LU6nDK9r3Fl
--- a/devtools/client/netmonitor/src/har/har-automation.js
+++ b/devtools/client/netmonitor/src/har/har-automation.js
@@ -163,16 +163,17 @@ HarAutomation.prototype = {
* Network panel (asynchronously) and saves it into a file.
*/
executeExport: function (data) {
let items = this.collector.getItems();
let form = this.toolbox.target.form;
let title = form.title || form.url;
let options = {
+ requestData: null,
getString: this.getString.bind(this),
view: this,
items: items,
};
options.defaultFileName = data.fileName;
options.compress = data.compress;
options.title = data.title || title;
--- a/devtools/client/netmonitor/src/har/har-builder.js
+++ b/devtools/client/netmonitor/src/har/har-builder.js
@@ -46,30 +46,32 @@ HarBuilder.prototype = {
/**
* This is the main method used to build the entire result HAR data.
* The process is asynchronous since it can involve additional RDP
* communication (e.g. resolving long strings).
*
* @returns {Promise} A promise that resolves to the HAR object when
* the entire build process is done.
*/
- build: function () {
+ build: async function () {
this.promises = [];
// Build basic structure for data.
let log = this.buildLog();
// Build entries.
for (let file of this._options.items) {
- log.entries.push(this.buildEntry(log, file));
+ log.entries.push(await this.buildEntry(log, file));
}
// Some data needs to be fetched from the backend during the
// build process, so wait till all is done.
- return Promise.all(this.promises).then(() => ({ log }));
+ await Promise.all(this.promises);
+
+ return { log };
},
// Helpers
buildLog: function () {
return {
version: HAR_VERSION,
creator: {
@@ -105,26 +107,26 @@ HarBuilder.prototype = {
}
this._pageMap[id] = page = this.buildPage(file);
log.pages.push(page);
return page;
},
- buildEntry: function (log, file) {
+ 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;
entry.request = this.buildRequest(file);
- entry.response = this.buildResponse(file);
+ entry.response = await this.buildResponse(file);
entry.cache = this.buildCache(file);
entry.timings = file.eventTimings ? file.eventTimings.timings : {};
if (file.remoteAddress) {
entry.serverIPAddress = file.remoteAddress;
}
if (file.remotePort) {
@@ -281,34 +283,34 @@ HarBuilder.prototype = {
});
});
}
});
return postData;
},
- buildResponse: function (file) {
+ buildResponse: async function (file) {
let response = {
status: 0
};
// Arbitrary value if it's aborted to make sure status has a number
if (file.status) {
response.status = parseInt(file.status, 10);
}
let responseHeaders = file.responseHeaders;
response.statusText = file.statusText || "";
response.httpVersion = file.httpVersion || "";
response.headers = this.buildHeaders(responseHeaders);
response.cookies = this.buildCookies(file.responseCookies);
- response.content = this.buildContent(file);
+ response.content = await this.buildContent(file);
let headers = responseHeaders ? responseHeaders.headers : null;
let headersSize = responseHeaders ? responseHeaders.headersSize : -1;
response.redirectURL = findValue(headers, "Location");
response.headersSize = headersSize;
// 'bodySize' is size of the received response body in bytes.
@@ -318,23 +320,29 @@ HarBuilder.prototype = {
response.bodySize = (response.status == 304) ? 0 : -1;
} else {
response.bodySize = file.transferredSize;
}
return response;
},
- buildContent: function (file) {
+ buildContent: async function (file) {
let content = {
mimeType: file.mimeType,
size: -1
};
+ // When using HarAutomation, HarCollector will automatically fetch responseContent,
+ // but when we use it from netmonitor, FirefoxDataProvider should fetch it itself
+ // lazily, via requestData.
let responseContent = file.responseContent;
+ if (!responseContent && this._options.requestData) {
+ responseContent = await this._options.requestData(file.id, "responseContent");
+ }
if (responseContent && responseContent.content) {
content.size = responseContent.content.size;
content.encoding = responseContent.content.encoding;
}
let includeBodies = this._options.includeResponseBodies;
let contentDiscarded = responseContent ?
responseContent.contentDiscarded : false;
--- 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
@@ -14,25 +14,26 @@ add_task(function* () {
let { tab, monitor } = yield initNetMonitor(SIMPLE_URL);
info("Starting test... ");
let { connector, store, windowRequire } = monitor.panelWin;
let Actions = windowRequire("devtools/client/netmonitor/src/actions/index");
let RequestListContextMenu = windowRequire(
"devtools/client/netmonitor/src/request-list-context-menu");
- let { getLongString, getTabTarget } = connector;
+ let { getLongString, getTabTarget, requestData } = connector;
store.dispatch(Actions.batchEnable(false));
let wait = waitForNetworkEvents(monitor, 1);
tab.linkedBrowser.reload();
yield wait;
- let contextMenu = new RequestListContextMenu({ getTabTarget, getLongString });
+ let contextMenu = new RequestListContextMenu({
+ getTabTarget, getLongString, requestData });
yield contextMenu.copyAllAsHar();
let jsonString = SpecialPowers.getClipboardData("text/unicode");
let har = JSON.parse(jsonString);
// Check out HAR log
isnot(har.log, null, "The HAR log must exist");
--- a/devtools/client/netmonitor/src/har/test/browser_net_har_post_data.js
+++ b/devtools/client/netmonitor/src/har/test/browser_net_har_post_data.js
@@ -11,29 +11,30 @@ add_task(function* () {
HAR_EXAMPLE_URL + "html_har_post-data-test-page.html");
info("Starting test... ");
let { connector, store, windowRequire } = monitor.panelWin;
let Actions = windowRequire("devtools/client/netmonitor/src/actions/index");
let RequestListContextMenu = windowRequire(
"devtools/client/netmonitor/src/request-list-context-menu");
- let { getLongString, getTabTarget } = connector;
+ let { getLongString, getTabTarget, requestData } = connector;
store.dispatch(Actions.batchEnable(false));
// Execute one POST request on the page and wait till its done.
let wait = waitForNetworkEvents(monitor, 0, 1);
yield ContentTask.spawn(tab.linkedBrowser, {}, function* () {
content.wrappedJSObject.executeTest();
});
yield wait;
// Copy HAR into the clipboard (asynchronous).
- let contextMenu = new RequestListContextMenu({ getTabTarget, getLongString });
+ let contextMenu = new RequestListContextMenu({
+ getTabTarget, getLongString, requestData });
let jsonString = yield contextMenu.copyAllAsHar();
let har = JSON.parse(jsonString);
// Check out the HAR log.
isnot(har.log, null, "The HAR log must exist");
is(har.log.pages.length, 1, "There must be one page");
is(har.log.entries.length, 1, "There must be one request");
--- a/devtools/client/netmonitor/src/har/test/browser_net_har_post_data_on_get.js
+++ b/devtools/client/netmonitor/src/har/test/browser_net_har_post_data_on_get.js
@@ -11,29 +11,30 @@ add_task(function* () {
HAR_EXAMPLE_URL + "html_har_post-data-test-page.html");
info("Starting test... ");
let { connector, store, windowRequire } = monitor.panelWin;
let Actions = windowRequire("devtools/client/netmonitor/src/actions/index");
let RequestListContextMenu = windowRequire(
"devtools/client/netmonitor/src/request-list-context-menu");
- let { getLongString, getTabTarget } = connector;
+ let { getLongString, getTabTarget, requestData } = connector;
store.dispatch(Actions.batchEnable(false));
// Execute one GET request on the page and wait till its done.
let wait = waitForNetworkEvents(monitor, 1);
yield ContentTask.spawn(tab.linkedBrowser, {}, function* () {
content.wrappedJSObject.executeTest3();
});
yield wait;
// Copy HAR into the clipboard (asynchronous).
- let contextMenu = new RequestListContextMenu({ getTabTarget, getLongString });
+ let contextMenu = new RequestListContextMenu({
+ getTabTarget, getLongString, requestData });
let jsonString = yield contextMenu.copyAllAsHar();
let har = JSON.parse(jsonString);
// Check out the HAR log.
isnot(har.log, null, "The HAR log must exist");
is(har.log.pages.length, 1, "There must be one page");
is(har.log.entries.length, 1, "There must be one request");
--- a/devtools/client/netmonitor/src/har/test/browser_net_har_throttle_upload.js
+++ b/devtools/client/netmonitor/src/har/test/browser_net_har_throttle_upload.js
@@ -15,17 +15,17 @@ function* throttleUploadTest(actuallyThr
HAR_EXAMPLE_URL + "html_har_post-data-test-page.html");
info("Starting test... (actuallyThrottle = " + actuallyThrottle + ")");
let { connector, store, windowRequire } = monitor.panelWin;
let Actions = windowRequire("devtools/client/netmonitor/src/actions/index");
let RequestListContextMenu = windowRequire(
"devtools/client/netmonitor/src/request-list-context-menu");
- let { getLongString, getTabTarget, setPreferences } = connector;
+ let { getLongString, getTabTarget, setPreferences, requestData } = connector;
store.dispatch(Actions.batchEnable(false));
const size = 4096;
const uploadSize = actuallyThrottle ? size / 3 : 0;
const request = {
"NetworkMonitor.throttleData": {
@@ -48,17 +48,18 @@ function* throttleUploadTest(actuallyThr
// Execute one POST request on the page and wait till its done.
let wait = waitForNetworkEvents(monitor, 0, 1);
yield ContentTask.spawn(tab.linkedBrowser, { size }, function* (args) {
content.wrappedJSObject.executeTest2(args.size);
});
yield wait;
// Copy HAR into the clipboard (asynchronous).
- let contextMenu = new RequestListContextMenu({ getTabTarget, getLongString });
+ let contextMenu = new RequestListContextMenu({
+ getTabTarget, getLongString, requestData });
let jsonString = yield contextMenu.copyAllAsHar();
let har = JSON.parse(jsonString);
// Check out the HAR log.
isnot(har.log, null, "The HAR log must exist");
is(har.log.pages.length, 1, "There must be one page");
is(har.log.entries.length, 1, "There must be one request");
--- a/devtools/client/netmonitor/src/request-list-context-menu.js
+++ b/devtools/client/netmonitor/src/request-list-context-menu.js
@@ -390,16 +390,17 @@ RequestListContextMenu.prototype = {
return HarExporter.save(this.getDefaultHarOptions());
},
getDefaultHarOptions() {
let form = this.getTabTarget().form;
let title = form.title || form.url;
return {
+ requestData: this.requestData,
getString: this.getLongString,
items: this.sortedRequests,
title: title
};
}
};
module.exports = RequestListContextMenu;