Bug 1350227 - [Performance] fetch data when request is selected
MozReview-Commit-ID: 97TMHQinDdr
--- a/devtools/client/netmonitor/src/actions/index.js
+++ b/devtools/client/netmonitor/src/actions/index.js
@@ -2,22 +2,20 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const batching = require("./batching");
const filters = require("./filters");
const requests = require("./requests");
-const selection = require("./selection");
const sort = require("./sort");
const timingMarkers = require("./timing-markers");
const ui = require("./ui");
Object.assign(exports,
batching,
filters,
requests,
- selection,
sort,
timingMarkers,
ui
);
--- a/devtools/client/netmonitor/src/actions/moz.build
+++ b/devtools/client/netmonitor/src/actions/moz.build
@@ -2,13 +2,12 @@
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
DevToolsModules(
'batching.js',
'filters.js',
'index.js',
'requests.js',
- 'selection.js',
'sort.js',
'timing-markers.js',
'ui.js',
)
--- a/devtools/client/netmonitor/src/actions/requests.js
+++ b/devtools/client/netmonitor/src/actions/requests.js
@@ -4,21 +4,31 @@
"use strict";
const {
ADD_REQUEST,
CLEAR_REQUESTS,
CLONE_SELECTED_REQUEST,
REMOVE_SELECTED_CUSTOM_REQUEST,
+ SELECT_REQUEST,
SEND_CUSTOM_REQUEST,
UPDATE_REQUEST,
} = require("../constants");
+const {
+ getDisplayedRequests,
+ getSelectedRequest,
+ getSortedRequests,
+} = require("../selectors/index");
+const { CurlUtils } = require("devtools/client/shared/curl");
+const { fetchHeaders } = require("../utils/request-utils");
+const { getLongString } = require("../utils/client");
const { NetMonitorController } = require("../netmonitor-controller");
-const { getSelectedRequest } = require("../selectors/index");
+
+const PAGE_SIZE_ITEM_COUNT_RATIO = 5;
function addRequest(id, data, batch) {
return {
type: ADD_REQUEST,
id,
data,
meta: { batch },
};
@@ -91,16 +101,177 @@ function removeSelectedCustomRequest() {
}
function clearRequests() {
return {
type: CLEAR_REQUESTS
};
}
+// update select request data asynchronizely
+async function updateRequestData(request) {
+ let {
+ responseCookies,
+ responseHeaders,
+ requestCookies,
+ requestHeaders,
+ requestPostData,
+ } = request;
+
+ // fetch requestHeaders
+ if (requestHeaders && requestHeaders.headers && requestHeaders.headers.length) {
+ let headers = await fetchHeaders(requestHeaders, getLongString);
+ if (headers) {
+ updateRequest(
+ request.id,
+ { requestHeaders: headers },
+ true,
+ );
+ }
+ }
+
+ // fetch responseHeaders
+ if (responseHeaders && responseHeaders.headers && responseHeaders.headers.length) {
+ let headers = await fetchHeaders(responseHeaders, getLongString);
+ if (headers) {
+ updateRequest(
+ request.id,
+ { responseHeaders: headers },
+ true,
+ );
+ }
+ }
+
+ // Search the POST data upload stream for request headers and add
+ // them as a separate property, different from the classic headers.
+ if (requestPostData && requestPostData.postData) {
+ let { text } = requestPostData.postData;
+ let postData = await getLongString(text);
+ const headers = CurlUtils.getHeadersFromMultipartText(postData);
+ const headersSize = headers.reduce((acc, { name, value }) => {
+ return acc + name.length + value.length + 2;
+ }, 0);
+ let payload = {};
+ requestPostData.postData.text = postData;
+ payload.requestPostData = Object.assign({}, requestPostData);
+ payload.requestHeadersFromUploadStream = { headers, headersSize };
+
+ updateRequest(request.id, payload, true);
+ }
+
+ // Fetch request and response cookies long value.
+ // Actor does not provide full sized cookie value when the value is too long
+ // To display values correctly, we need fetch them in each request.
+ if (requestCookies) {
+ let reqCookies = [];
+ // request store cookies in requestCookies or requestCookies.cookies
+ let cookies = requestCookies.cookies ?
+ requestCookies.cookies : requestCookies;
+ // make sure cookies is iterable
+ if (typeof cookies[Symbol.iterator] === "function") {
+ for (let cookie of cookies) {
+ reqCookies.push(Object.assign({}, cookie, {
+ value: await getLongString(cookie.value),
+ }));
+ }
+ if (reqCookies.length) {
+ updateRequest(request.id, { requestCookies: reqCookies }, true);
+ }
+ }
+ }
+
+ if (responseCookies) {
+ let resCookies = [];
+ // response store cookies in responseCookies or responseCookies.cookies
+ let cookies = responseCookies.cookies ?
+ responseCookies.cookies : responseCookies;
+ // make sure cookies is iterable
+ if (typeof cookies[Symbol.iterator] === "function") {
+ for (let cookie of cookies) {
+ resCookies.push(Object.assign({}, cookie, {
+ value: await getLongString(cookie.value),
+ }));
+ }
+ if (resCookies.length) {
+ updateRequest(request.id, { responseCookies: resCookies }, true);
+ }
+ }
+ }
+}
+
+/**
+ * Select request with a given id.
+ */
+function selectTheRequest(id) {
+ return {
+ type: SELECT_REQUEST,
+ id,
+ };
+}
+
+/**
+ * Select request with a given id with thunk.
+ */
+function selectRequest(id) {
+ return (dispatch, getState) => {
+ const selected = getSelectedRequest(getState());
+ if (selected) {
+ updateRequestData(selected);
+ }
+
+ dispatch(selectTheRequest(id));
+ };
+}
+
+/**
+ * Select request with a given index (sorted order)
+ */
+function selectRequestByIndex(index) {
+ return (dispatch, getState) => {
+ const requests = getSortedRequests(getState());
+ let itemId;
+ if (index >= 0 && index < requests.size) {
+ itemId = requests.get(index).id;
+ }
+ dispatch(selectRequest(itemId));
+ };
+}
+
+/**
+ * Move the selection up to down according to the "delta" parameter. Possible values:
+ * - Number: positive or negative, move up or down by specified distance
+ * - "PAGE_UP" | "PAGE_DOWN" (String): page up or page down
+ * - +Infinity | -Infinity: move to the start or end of the list
+ */
+function selectDelta(delta) {
+ return (dispatch, getState) => {
+ const state = getState();
+ const requests = getDisplayedRequests(state);
+
+ if (requests.isEmpty()) {
+ return;
+ }
+
+ const selIndex = requests.findIndex(r => r.id === state.requests.selectedId);
+
+ if (delta === "PAGE_DOWN") {
+ delta = Math.ceil(requests.size / PAGE_SIZE_ITEM_COUNT_RATIO);
+ } else if (delta === "PAGE_UP") {
+ delta = -Math.ceil(requests.size / PAGE_SIZE_ITEM_COUNT_RATIO);
+ }
+
+ const newIndex = Math.min(Math.max(0, selIndex + delta), requests.size - 1);
+ const newItem = requests.get(newIndex);
+ dispatch(selectRequest(newItem.id));
+ };
+}
+
module.exports = {
addRequest,
clearRequests,
cloneSelectedRequest,
removeSelectedCustomRequest,
+ selectRequest,
+ selectRequestByIndex,
+ selectDelta,
sendCustomRequest,
updateRequest,
};
deleted file mode 100644
--- a/devtools/client/netmonitor/src/actions/selection.js
+++ /dev/null
@@ -1,72 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-"use strict";
-
-const { SELECT_REQUEST } = require("../constants");
-const {
- getDisplayedRequests,
- getSortedRequests,
-} = require("../selectors/index");
-
-const PAGE_SIZE_ITEM_COUNT_RATIO = 5;
-
-/**
- * Select request with a given id.
- */
-function selectRequest(id) {
- return {
- type: SELECT_REQUEST,
- id,
- };
-}
-
-/**
- * Select request with a given index (sorted order)
- */
-function selectRequestByIndex(index) {
- return (dispatch, getState) => {
- const requests = getSortedRequests(getState());
- let itemId;
- if (index >= 0 && index < requests.size) {
- itemId = requests.get(index).id;
- }
- dispatch(selectRequest(itemId));
- };
-}
-
-/**
- * Move the selection up to down according to the "delta" parameter. Possible values:
- * - Number: positive or negative, move up or down by specified distance
- * - "PAGE_UP" | "PAGE_DOWN" (String): page up or page down
- * - +Infinity | -Infinity: move to the start or end of the list
- */
-function selectDelta(delta) {
- return (dispatch, getState) => {
- const state = getState();
- const requests = getDisplayedRequests(state);
-
- if (requests.isEmpty()) {
- return;
- }
-
- const selIndex = requests.findIndex(r => r.id === state.requests.selectedId);
-
- if (delta === "PAGE_DOWN") {
- delta = Math.ceil(requests.size / PAGE_SIZE_ITEM_COUNT_RATIO);
- } else if (delta === "PAGE_UP") {
- delta = -Math.ceil(requests.size / PAGE_SIZE_ITEM_COUNT_RATIO);
- }
-
- const newIndex = Math.min(Math.max(0, selIndex + delta), requests.size - 1);
- const newItem = requests.get(newIndex);
- dispatch(selectRequest(newItem.id));
- };
-}
-
-module.exports = {
- selectRequest,
- selectRequestByIndex,
- selectDelta,
-};
--- a/devtools/client/netmonitor/src/netmonitor-controller.js
+++ b/devtools/client/netmonitor/src/netmonitor-controller.js
@@ -1,25 +1,21 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const { TimelineFront } = require("devtools/shared/fronts/timeline");
-const { CurlUtils } = require("devtools/client/shared/curl");
const { ACTIVITY_TYPE, EVENTS } = require("./constants");
const {
getRequestById,
getDisplayedRequestById,
} = require("./selectors/index");
-const {
- fetchHeaders,
- formDataURI,
-} = require("./utils/request-utils");
+const { formDataURI } = require("./utils/request-utils");
const {
getLongString,
getWebConsoleClient,
onFirefoxConnect,
onFirefoxDisconnect,
} = require("./utils/client");
/**
@@ -224,16 +220,17 @@ var NetMonitorController = {
}).then(standBy);
}
this._currentActivity = ACTIVITY_TYPE.NONE;
return Promise.reject(new Error("Invalid activity type"));
},
/**
* Selects the specified request in the waterfall and opens the details view.
+ * Used by webconsole
*
* @param string requestId
* The actor ID of the request to inspect.
* @return object
* A promise resolved once the task finishes.
*/
inspectRequest(requestId) {
// Look for the request in the existing ones or wait for it to appear, if
@@ -425,48 +422,20 @@ NetworkEventsHandler.prototype = {
},
true
)
.then(() => window.emit(EVENTS.REQUEST_ADDED, id));
},
async updateRequest(id, data) {
await this.actions.updateRequest(id, data, true);
- let {
- responseContent,
- responseCookies,
- responseHeaders,
- requestCookies,
- requestHeaders,
- requestPostData,
- } = data;
+ let { responseContent } = data;
let request = getRequestById(window.gStore.getState(), id);
- if (requestHeaders && requestHeaders.headers && requestHeaders.headers.length) {
- let headers = await fetchHeaders(requestHeaders, getLongString);
- if (headers) {
- await this.actions.updateRequest(
- id,
- { requestHeaders: headers },
- true,
- );
- }
- }
-
- if (responseHeaders && responseHeaders.headers && responseHeaders.headers.length) {
- let headers = await fetchHeaders(responseHeaders, getLongString);
- if (headers) {
- await this.actions.updateRequest(
- id,
- { responseHeaders: headers },
- true,
- );
- }
- }
-
+ // fetch image
if (request && responseContent && responseContent.content) {
let { mimeType } = request;
let { text, encoding } = responseContent.content;
let response = await getLongString(text);
let payload = {};
if (mimeType.includes("image/")) {
payload.responseContentDataUri = formDataURI(mimeType, encoding, response);
@@ -476,72 +445,16 @@ NetworkEventsHandler.prototype = {
payload.responseContent = responseContent;
await this.actions.updateRequest(id, payload, true);
if (mimeType.includes("image/")) {
window.emit(EVENTS.RESPONSE_IMAGE_THUMBNAIL_DISPLAYED);
}
}
-
- // Search the POST data upload stream for request headers and add
- // them as a separate property, different from the classic headers.
- if (requestPostData && requestPostData.postData) {
- let { text } = requestPostData.postData;
- let postData = await getLongString(text);
- const headers = CurlUtils.getHeadersFromMultipartText(postData);
- const headersSize = headers.reduce((acc, { name, value }) => {
- return acc + name.length + value.length + 2;
- }, 0);
- let payload = {};
- requestPostData.postData.text = postData;
- payload.requestPostData = Object.assign({}, requestPostData);
- payload.requestHeadersFromUploadStream = { headers, headersSize };
-
- await this.actions.updateRequest(id, payload, true);
- }
-
- // Fetch request and response cookies long value.
- // Actor does not provide full sized cookie value when the value is too long
- // To display values correctly, we need fetch them in each request.
- if (requestCookies) {
- let reqCookies = [];
- // request store cookies in requestCookies or requestCookies.cookies
- let cookies = requestCookies.cookies ?
- requestCookies.cookies : requestCookies;
- // make sure cookies is iterable
- if (typeof cookies[Symbol.iterator] === "function") {
- for (let cookie of cookies) {
- reqCookies.push(Object.assign({}, cookie, {
- value: await getLongString(cookie.value),
- }));
- }
- if (reqCookies.length) {
- await this.actions.updateRequest(id, { requestCookies: reqCookies }, true);
- }
- }
- }
-
- if (responseCookies) {
- let resCookies = [];
- // response store cookies in responseCookies or responseCookies.cookies
- let cookies = responseCookies.cookies ?
- responseCookies.cookies : responseCookies;
- // make sure cookies is iterable
- if (typeof cookies[Symbol.iterator] === "function") {
- for (let cookie of cookies) {
- resCookies.push(Object.assign({}, cookie, {
- value: await getLongString(cookie.value),
- }));
- }
- if (resCookies.length) {
- await this.actions.updateRequest(id, { responseCookies: resCookies }, true);
- }
- }
- }
},
/**
* The "networkEventUpdate" message type handler.
*
* @param string type
* Message type.
* @param object packet