--- a/devtools/client/netmonitor/src/connector/firefox-data-provider.js
+++ b/devtools/client/netmonitor/src/connector/firefox-data-provider.js
@@ -314,16 +314,19 @@ class FirefoxDataProvider {
},
startedDateTime,
} = networkInfo;
// Create tracking record for this request.
this.rdpRequestMap.set(actor, {
requestHeaders: false,
requestCookies: false,
+ responseHeaders: false,
+ responseCookies: false,
+ securityInfo: false,
eventTimings: false,
responseContent: false,
});
this.addRequest(actor, {
cause,
fromCache,
fromServiceWorker,
@@ -345,91 +348,54 @@ class FirefoxDataProvider {
*/
onNetworkEventUpdate(type, data) {
let { packet, networkInfo } = data;
let { actor } = networkInfo;
let { updateType } = packet;
switch (updateType) {
case "requestHeaders":
- this.requestData(actor, updateType).then(response => {
- this.onRequestHeaders(response)
- .then(() => this.onDataReceived(actor, updateType));
- emit(EVENTS.UPDATING_REQUEST_HEADERS, actor);
- });
- break;
case "requestCookies":
- this.requestData(actor, updateType).then(response => {
- this.onRequestCookies(response)
- .then(() => this.onDataReceived(actor, updateType));
- emit(EVENTS.UPDATING_REQUEST_COOKIES, actor);
- });
- break;
case "requestPostData":
- this.requestData(actor, updateType).then(response => {
- this.onRequestPostData(response)
- .then(() => this.onDataReceived(actor, updateType));
- emit(EVENTS.UPDATING_REQUEST_POST_DATA, actor);
- });
+ case "responseHeaders":
+ case "responseCookies":
+ this.requestData(actor, updateType);
break;
case "securityInfo":
this.updateRequest(actor, {
securityState: networkInfo.securityInfo,
}).then(() => {
- this.requestData(actor, updateType).then(response => {
- this.onSecurityInfo(response)
- .then(() => this.onDataReceived(actor, updateType));
- emit(EVENTS.UPDATING_SECURITY_INFO, actor);
- });
- });
- break;
- case "responseHeaders":
- this.requestData(actor, updateType).then(response => {
- this.onResponseHeaders(response)
- .then(() => this.onDataReceived(actor, updateType));
- emit(EVENTS.UPDATING_RESPONSE_HEADERS, actor);
- });
- break;
- case "responseCookies":
- this.requestData(actor, updateType).then(response => {
- this.onResponseCookies(response)
- .then(() => this.onDataReceived(actor, updateType));
- emit(EVENTS.UPDATING_RESPONSE_COOKIES, actor);
+ this.requestData(actor, updateType);
});
break;
case "responseStart":
this.updateRequest(actor, {
httpVersion: networkInfo.response.httpVersion,
remoteAddress: networkInfo.response.remoteAddress,
remotePort: networkInfo.response.remotePort,
status: networkInfo.response.status,
statusText: networkInfo.response.statusText,
headersSize: networkInfo.response.headersSize
}).then(() => {
emit(EVENTS.STARTED_RECEIVING_RESPONSE, actor);
});
break;
case "responseContent":
- this.requestData(actor, updateType).then(response => {
- this.onResponseContent({
- contentSize: networkInfo.response.bodySize,
- transferredSize: networkInfo.response.transferredSize,
- mimeType: networkInfo.response.content.mimeType
- }, response).then(() => this.onDataReceived(actor, updateType));
- emit(EVENTS.UPDATING_RESPONSE_CONTENT, actor);
+ this.updateRequest(actor, {
+ contentSize: networkInfo.response.bodySize,
+ transferredSize: networkInfo.response.transferredSize,
+ mimeType: networkInfo.response.content.mimeType
+ }).then(() => {
+ this.requestData(actor, updateType);
});
break;
case "eventTimings":
this.updateRequest(actor, { totalTime: networkInfo.totalTime })
.then(() => {
- this.requestData(actor, updateType).then(response => {
- this.onEventTimings(response)
- .then(() => this.onDataReceived(actor, updateType));
- emit(EVENTS.UPDATING_EVENT_TIMINGS, actor);
- });
+ this.requestData(actor, updateType);
});
break;
}
emit(EVENTS.NETWORK_EVENT_UPDATED, actor);
}
/**
@@ -442,61 +408,71 @@ class FirefoxDataProvider {
* It also nicely returns a promise.
*
* @param {string} actor actor id (used as request id)
* @param {string} method identifier of the data we want to fetch
*
* @return {Promise} return a promise resolved when data are received.
*/
requestData(actor, method) {
- let record = this.rdpRequestMap.get(actor);
-
// All RDP requests related to the given actor will be collected
// in the same record.
+ let record = this.rdpRequestMap.get(actor);
if (!record) {
- record = {};
+ dump(new Error().stack+"\n");
}
- // If data has been already requested return the same promise.
- if (record.method) {
- return record.method;
+ // If data has been already requested and is still a promise,
+ // returns the same promise.
+ if (record[method] instanceof Promise) {
+ return record[method];
}
// Calculate real name of the client getter.
- let realMethodName = "get" + method.charAt(0).toUpperCase() +
+ let clientMethodName = "get" + method.charAt(0).toUpperCase() +
method.slice(1);
+ // The name of the callback that processes request response
+ let callbackMethodName = "on" + method.charAt(0).toUpperCase() +
+ method.slice(1);
+ // And the event to fire before updating this data
+ let updatingEventName = "UPDATING_" + method.toUpperCase()
+ .replace(/(REQUEST|RESPONSE|EVENT|SECURITY)/, "$1_");
// Request data from the backend.
- let promise = new Promise((resolve, reject) => {
- if (typeof this.webConsoleClient[realMethodName] == "function") {
- this.webConsoleClient[realMethodName](actor, response => {
- // Resolve incoming HTTP details data-promise.
- resolve(response);
- });
+ let promise = (async () => {
+ if (typeof this.webConsoleClient[clientMethodName] == "function") {
+ emit(EVENTS[updatingEventName], actor);
+ // Resolve incoming HTTP details data-promise.
+ let response = await this.webConsoleClient[clientMethodName](actor);
+ await this[callbackMethodName](response);
+
+ // Once we got the data toggle the Map item to `true` in order to
+ // make isRequestPayloadReady return `true` once all the data is fetched.
+ let record = this.rdpRequestMap.get(actor);
+ if (record) {
+ record[method] = true;
+ }
+
+ this.onDataReceived(actor, method);
+ return response;
} else {
- reject(new Error("Error: No such client method!"));
+ throw new Error("Error: No such client method '" + clientMethodName + "'!");
}
- });
+ })();
- // Store the promise in order to know about RDP requests
- // in progress.
+ // Store the promise in order to know about RDP requests in progress.
record[method] = promise;
return promise;
}
/**
* Executed when new data are received from the backend.
*/
async onDataReceived(actor, type) {
- let record = this.rdpRequestMap.get(actor);
- if (record) {
- record[type] = true;
- }
-
if (this.isRequestPayloadReady(actor)) {
let payloadFromQueue = this.getRequestFromQueue(actor).payload;
// Clean up
this.cleanUpQueue(actor);
this.rdpRequestMap.delete(actor);
let { updateRequest } = this.actions;
@@ -582,24 +558,27 @@ class FirefoxDataProvider {
return this.updateRequest(response.from, {
responseCookies: response
}).then(() => {
emit(EVENTS.RECEIVED_RESPONSE_COOKIES, response.from);
});
}
/**
- * Handles additional information received for a "responseContent" packet.
+ * Handles additional information received via "getResponseContent" request.
*
- * @param {object} data the message received from the server event.
* @param {object} response the message received from the server.
*/
- onResponseContent(data, response) {
- let payload = Object.assign({ responseContent: response }, data);
- return this.updateRequest(response.from, payload).then(() => {
+ onResponseContent(response) {
+ this.updateRequest(response.from, {
+ // We have to ensure passing mimeType as fetchResponseContent needs it from updateRequest.
+ // It will convert the LongString in `response.content.text` to a string.
+ mimeType: response.content.mimeType,
+ responseContent: response,
+ }).then(() => {
emit(EVENTS.RECEIVED_RESPONSE_CONTENT, response.from);
});
}
/**
* Handles additional information received for a "eventTimings" packet.
*
* @param {object} response the message received from the server.