--- a/devtools/client/netmonitor/src/components/CookiesPanel.js
+++ b/devtools/client/netmonitor/src/components/CookiesPanel.js
@@ -3,16 +3,17 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const { Component, createFactory } = require("devtools/client/shared/vendor/react");
const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
const dom = require("devtools/client/shared/vendor/react-dom-factories");
const { L10N } = require("../utils/l10n");
+const { fetchNetworkUpdatePacket } = require("../utils/request-utils");
const { sortObjectKeys } = require("../utils/sort-utils");
// Component
const PropertiesView = createFactory(require("./PropertiesView"));
const { div } = dom;
const COOKIES_EMPTY_TEXT = L10N.getStr("cookiesEmptyText");
@@ -33,34 +34,29 @@ class CookiesPanel extends Component {
return {
connector: PropTypes.object.isRequired,
openLink: PropTypes.func,
request: PropTypes.object.isRequired,
};
}
componentDidMount() {
- this.maybeFetchCookies(this.props);
+ let { connector, request } = this.props;
+ fetchNetworkUpdatePacket(connector.requestData, request, [
+ "requestCookies",
+ "responseCookies",
+ ]);
}
componentWillReceiveProps(nextProps) {
- this.maybeFetchCookies(nextProps);
- }
-
- /**
- * When switching to another request, lazily fetch request cookies
- * from the backend. The panel will first be empty and then display the content.
- */
- maybeFetchCookies(props) {
- if (props.request.requestCookiesAvailable && !props.request.requestCookies) {
- props.connector.requestData(props.request.id, "requestCookies");
- }
- if (props.request.responseCookiesAvailable && !props.request.responseCookies) {
- props.connector.requestData(props.request.id, "responseCookies");
- }
+ let { connector, request } = nextProps;
+ fetchNetworkUpdatePacket(connector.requestData, request, [
+ "requestCookies",
+ "responseCookies",
+ ]);
}
/**
* Mapping array to dict for TreeView usage.
* Since TreeView only support Object(dict) format.
*
* @param {Object[]} arr - key-value pair array like cookies or params
* @returns {Object}
--- a/devtools/client/netmonitor/src/components/CustomRequestPanel.js
+++ b/devtools/client/netmonitor/src/components/CustomRequestPanel.js
@@ -4,16 +4,17 @@
"use strict";
const { Component } = require("devtools/client/shared/vendor/react");
const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
const dom = require("devtools/client/shared/vendor/react-dom-factories");
const { connect } = require("devtools/client/shared/vendor/react-redux");
const { L10N } = require("../utils/l10n");
+const { fetchNetworkUpdatePacket } = require("../utils/request-utils");
const Actions = require("../actions/index");
const { getSelectedRequest } = require("../selectors/index");
const {
getUrlQuery,
parseQueryString,
writeHeaderText,
} = require("../utils/request-utils");
@@ -43,35 +44,31 @@ class CustomRequestPanel extends Compone
removeSelectedCustomRequest: PropTypes.func.isRequired,
request: PropTypes.object,
sendCustomRequest: PropTypes.func.isRequired,
updateRequest: PropTypes.func.isRequired,
};
}
componentDidMount() {
- this.maybeFetchPostData(this.props);
+ let { request, connector } = this.props;
+ fetchNetworkUpdatePacket(connector.requestData, request, [
+ "requestHeaders",
+ "responseHeaders",
+ "requestPostData",
+ ]);
}
componentWillReceiveProps(nextProps) {
- this.maybeFetchPostData(nextProps);
- }
-
- /**
- * When switching to another request, lazily fetch request post data
- * from the backend. The panel will first be empty and then display the content.
- */
- maybeFetchPostData(props) {
- if (props.request.requestPostDataAvailable &&
- (!props.request.requestPostData ||
- !props.request.requestPostData.postData.text)) {
- // This method will set `props.request.requestPostData`
- // asynchronously and force another render.
- props.connector.requestData(props.request.id, "requestPostData");
- }
+ let { request, connector } = nextProps;
+ fetchNetworkUpdatePacket(connector.requestData, request, [
+ "requestHeaders",
+ "responseHeaders",
+ "requestPostData",
+ ]);
}
/**
* Parse a text representation of a name[divider]value list with
* the given name regex and divider character.
*
* @param {string} text - Text of list
* @return {array} array of headers info {name, value}
--- a/devtools/client/netmonitor/src/components/HeadersPanel.js
+++ b/devtools/client/netmonitor/src/components/HeadersPanel.js
@@ -11,17 +11,20 @@ const {
getFormattedIPAndPort,
getFormattedSize,
} = require("../utils/format-utils");
const { L10N } = require("../utils/l10n");
const {
getHeadersURL,
getHTTPStatusCodeURL,
} = require("../utils/mdn-utils");
-const { writeHeaderText } = require("../utils/request-utils");
+const {
+ fetchNetworkUpdatePacket,
+ writeHeaderText,
+} = require("../utils/request-utils");
const { sortObjectKeys } = require("../utils/sort-utils");
// Components
const { REPS, MODE } = require("devtools/client/shared/components/reps/reps");
const MDNLink = createFactory(require("./MdnLink"));
const PropertiesView = createFactory(require("./PropertiesView"));
const { Rep } = REPS;
@@ -63,40 +66,34 @@ class HeadersPanel extends Component {
this.state = {
rawHeadersOpened: false,
};
this.getProperties = this.getProperties.bind(this);
this.toggleRawHeaders = this.toggleRawHeaders.bind(this);
this.renderSummary = this.renderSummary.bind(this);
this.renderValue = this.renderValue.bind(this);
- this.maybeFetchPostData = this.maybeFetchPostData.bind(this);
}
componentDidMount() {
- this.maybeFetchPostData(this.props);
+ let { request, connector } = this.props;
+ fetchNetworkUpdatePacket(connector.requestData, request, [
+ "requestHeaders",
+ "responseHeaders",
+ "requestPostData",
+ ]);
}
componentWillReceiveProps(nextProps) {
- this.maybeFetchPostData(nextProps);
- }
-
- /**
- * When switching to another request, lazily fetch request post data
- * from the backend. The panel will first be empty and then display the content.
- * Fetching post data is used for updating requestHeadersFromUploadStream section,
- */
- maybeFetchPostData(props) {
- if (props.request.requestPostDataAvailable &&
- (!props.request.requestPostData ||
- !props.request.requestPostData.postData.text)) {
- // This method will set `props.request.requestPostData`
- // asynchronously and force another render.
- props.connector.requestData(props.request.id, "requestPostData");
- }
+ let { request, connector } = nextProps;
+ fetchNetworkUpdatePacket(connector.requestData, request, [
+ "requestHeaders",
+ "responseHeaders",
+ "requestPostData",
+ ]);
}
getProperties(headers, title) {
if (headers && headers.headers.length) {
let headerKey = `${title} (${getFormattedSize(headers.headersSize, 3)})`;
let propertiesResult = {
[headerKey]:
headers.headers.reduce((acc, { name, value }) =>
--- a/devtools/client/netmonitor/src/components/ParamsPanel.js
+++ b/devtools/client/netmonitor/src/components/ParamsPanel.js
@@ -4,17 +4,22 @@
"use strict";
const { Component, createFactory } = require("devtools/client/shared/vendor/react");
const dom = require("devtools/client/shared/vendor/react-dom-factories");
const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
const { connect } = require("devtools/client/shared/vendor/react-redux");
const { L10N } = require("../utils/l10n");
-const { getUrlQuery, parseQueryString, parseFormData } = require("../utils/request-utils");
+const {
+ fetchNetworkUpdatePacket,
+ getUrlQuery,
+ parseQueryString,
+ parseFormData,
+} = require("../utils/request-utils");
const { sortObjectKeys } = require("../utils/sort-utils");
const { updateFormDataSections } = require("../utils/request-utils");
const Actions = require("../actions/index");
// Components
const PropertiesView = createFactory(require("./PropertiesView"));
const { div } = dom;
@@ -46,40 +51,28 @@ class ParamsPanel extends Component {
};
}
constructor(props) {
super(props);
}
componentDidMount() {
- this.maybeFetchPostData(this.props);
+ let { request, connector } = this.props;
+ fetchNetworkUpdatePacket(connector.requestData, request, ["requestPostData"]);
updateFormDataSections(this.props);
}
componentWillReceiveProps(nextProps) {
- this.maybeFetchPostData(nextProps);
+ let { request, connector } = nextProps;
+ fetchNetworkUpdatePacket(connector.requestData, request, ["requestPostData"]);
updateFormDataSections(nextProps);
}
/**
- * When switching to another request, lazily fetch request post data
- * from the backend. The panel will first be empty and then display the content.
- */
- maybeFetchPostData(props) {
- if (props.request.requestPostDataAvailable &&
- (!props.request.requestPostData ||
- !props.request.requestPostData.postData.text)) {
- // This method will set `props.request.requestPostData`
- // asynchronously and force another render.
- props.connector.requestData(props.request.id, "requestPostData");
- }
- }
-
- /**
* Mapping array to dict for TreeView usage.
* Since TreeView only support Object(dict) format.
* This function also deal with duplicate key case
* (for multiple selection and query params with same keys)
*
* @param {Object[]} arr - key-value pair array like query or form params
* @returns {Object} Rep compatible object
*/
--- a/devtools/client/netmonitor/src/components/RequestListColumnCookies.js
+++ b/devtools/client/netmonitor/src/components/RequestListColumnCookies.js
@@ -2,52 +2,46 @@
* 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 { Component } = require("devtools/client/shared/vendor/react");
const dom = require("devtools/client/shared/vendor/react-dom-factories");
const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
+const { fetchNetworkUpdatePacket } = require("../utils/request-utils");
const { div } = dom;
class RequestListColumnCookies extends Component {
static get propTypes() {
return {
connector: PropTypes.object.isRequired,
item: PropTypes.object.isRequired,
};
}
componentDidMount() {
- this.maybeFetchRequestCookies(this.props);
+ let { item, connector } = this.props;
+ fetchNetworkUpdatePacket(connector.requestData, item, ["requestCookies"]);
}
componentWillReceiveProps(nextProps) {
- this.maybeFetchRequestCookies(nextProps);
+ let { item, connector } = nextProps;
+ fetchNetworkUpdatePacket(connector.requestData, item, ["requestCookies"]);
}
shouldComponentUpdate(nextProps) {
let { requestCookies: currRequestCookies = { cookies: [] } } = this.props.item;
let { requestCookies: nextRequestCookies = { cookies: [] } } = nextProps.item;
currRequestCookies = currRequestCookies.cookies || currRequestCookies;
nextRequestCookies = nextRequestCookies.cookies || nextRequestCookies;
return currRequestCookies !== nextRequestCookies;
}
- /**
- * Lazily fetch request cookies from the backend.
- */
- maybeFetchRequestCookies(props) {
- if (props.item.requestCookiesAvailable && !props.requestCookies) {
- props.connector.requestData(props.item.id, "requestCookies");
- }
- }
-
render() {
let { requestCookies = { cookies: [] } } = this.props.item;
requestCookies = requestCookies.cookies || requestCookies;
let requestCookiesLength = requestCookies.length > 0 ? requestCookies.length : "";
return (
div({
className: "requests-list-column requests-list-cookies",
title: requestCookiesLength
--- a/devtools/client/netmonitor/src/components/RequestListColumnSetCookies.js
+++ b/devtools/client/netmonitor/src/components/RequestListColumnSetCookies.js
@@ -2,52 +2,46 @@
* 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 { Component } = require("devtools/client/shared/vendor/react");
const dom = require("devtools/client/shared/vendor/react-dom-factories");
const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
+const { fetchNetworkUpdatePacket } = require("../utils/request-utils");
const { div } = dom;
class RequestListColumnSetCookies extends Component {
static get propTypes() {
return {
connector: PropTypes.object.isRequired,
item: PropTypes.object.isRequired,
};
}
componentDidMount() {
- this.maybeFetchResponseCookies(this.props);
+ let { item, connector } = this.props;
+ fetchNetworkUpdatePacket(connector.requestData, item, ["responseCookies"]);
}
componentWillReceiveProps(nextProps) {
- this.maybeFetchResponseCookies(nextProps);
+ let { item, connector } = nextProps;
+ fetchNetworkUpdatePacket(connector.requestData, item, ["responseCookies"]);
}
shouldComponentUpdate(nextProps) {
let { responseCookies: currResponseCookies = { cookies: [] } } = this.props.item;
let { responseCookies: nextResponseCookies = { cookies: [] } } = nextProps.item;
currResponseCookies = currResponseCookies.cookies || currResponseCookies;
nextResponseCookies = nextResponseCookies.cookies || nextResponseCookies;
return currResponseCookies !== nextResponseCookies;
}
- /**
- * Lazily fetch response cookies from the backend.
- */
- maybeFetchResponseCookies(props) {
- if (props.item.responseCookiesAvailable && !props.responseCookies) {
- props.connector.requestData(props.item.id, "responseCookies");
- }
- }
-
render() {
let { responseCookies = { cookies: [] } } = this.props.item;
responseCookies = responseCookies.cookies || responseCookies;
let responseCookiesLength = responseCookies.length > 0 ? responseCookies.length : "";
return (
div({
className: "requests-list-column requests-list-set-cookies",
title: responseCookiesLength
--- a/devtools/client/netmonitor/src/components/ResponsePanel.js
+++ b/devtools/client/netmonitor/src/components/ResponsePanel.js
@@ -5,16 +5,17 @@
"use strict";
const { Component, createFactory } = require("devtools/client/shared/vendor/react");
const dom = require("devtools/client/shared/vendor/react-dom-factories");
const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
const { L10N } = require("../utils/l10n");
const {
decodeUnicodeBase64,
+ fetchNetworkUpdatePacket,
formDataURI,
getUrlBaseName,
} = require("../utils/request-utils");
const { Filters } = require("../utils/filter-predicates");
// Components
const PropertiesView = createFactory(require("./PropertiesView"));
@@ -52,36 +53,23 @@ class ResponsePanel extends Component {
},
};
this.updateImageDimemsions = this.updateImageDimemsions.bind(this);
this.isJSON = this.isJSON.bind(this);
}
componentDidMount() {
- this.maybeFetchResponseContent(this.props);
+ let { request, connector } = this.props;
+ fetchNetworkUpdatePacket(connector.requestData, request, ["responseContent"]);
}
componentWillReceiveProps(nextProps) {
- this.maybeFetchResponseContent(nextProps);
- }
-
- /**
- * When switching to another request, lazily fetch response content
- * from the backend. The Response Panel will first be empty and then
- * display the content.
- */
- maybeFetchResponseContent(props) {
- if (props.request.responseContentAvailable &&
- (!props.request.responseContent ||
- !props.request.responseContent.content)) {
- // This method will set `props.request.responseContent.content`
- // asynchronously and force another render.
- props.connector.requestData(props.request.id, "responseContent");
- }
+ let { request, connector } = nextProps;
+ fetchNetworkUpdatePacket(connector.requestData, request, ["responseContent"]);
}
updateImageDimemsions({ target }) {
this.setState({
imageDimensions: {
width: target.naturalWidth,
height: target.naturalHeight,
},
--- a/devtools/client/netmonitor/src/components/SecurityPanel.js
+++ b/devtools/client/netmonitor/src/components/SecurityPanel.js
@@ -6,17 +6,20 @@
const {
Component,
createFactory,
} = require("devtools/client/shared/vendor/react");
const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
const dom = require("devtools/client/shared/vendor/react-dom-factories");
const { L10N } = require("../utils/l10n");
-const { getUrlHost } = require("../utils/request-utils");
+const {
+ fetchNetworkUpdatePacket,
+ getUrlHost,
+} = require("../utils/request-utils");
// Components
const TreeViewClass = require("devtools/client/shared/components/tree/TreeView");
const PropertiesView = createFactory(require("./PropertiesView"));
const { div, input, span } = dom;
const NOT_AVAILABLE = L10N.getStr("netmonitor.security.notAvailable");
const ERROR_LABEL = L10N.getStr("netmonitor.security.error");
@@ -55,34 +58,23 @@ class SecurityPanel extends Component {
return {
connector: PropTypes.object.isRequired,
openLink: PropTypes.func,
request: PropTypes.object.isRequired,
};
}
componentDidMount() {
- this.maybeFetchSecurityInfo(this.props);
+ let { request, connector } = this.props;
+ fetchNetworkUpdatePacket(connector.requestData, request, ["securityInfo"]);
}
componentWillReceiveProps(nextProps) {
- this.maybeFetchSecurityInfo(nextProps);
- }
-
- /**
- * When switching to another request, lazily fetch securityInfo
- * from the backend. The Security Panel will first be empty and then
- * display the content.
- */
- maybeFetchSecurityInfo(props) {
- if (!props.request.securityInfo) {
- // This method will set `props.request.securityInfo`
- // asynchronously and force another render.
- props.connector.requestData(props.request.id, "securityInfo");
- }
+ let { request, connector } = nextProps;
+ fetchNetworkUpdatePacket(connector.requestData, request, ["securityInfo"]);
}
renderValue(props, weaknessReasons = []) {
const { member, value } = props;
// Hide object summary
if (typeof member.value === "object") {
return null;
--- a/devtools/client/netmonitor/src/components/StackTracePanel.js
+++ b/devtools/client/netmonitor/src/components/StackTracePanel.js
@@ -2,16 +2,17 @@
* 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 { Component, createFactory } = require("devtools/client/shared/vendor/react");
const dom = require("devtools/client/shared/vendor/react-dom-factories");
const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
+const { fetchNetworkUpdatePacket } = require("../utils/request-utils");
const { div } = dom;
// Components
const StackTrace = createFactory(require("devtools/client/shared/components/StackTrace"));
/**
* This component represents a side panel responsible for
@@ -27,41 +28,27 @@ class StackTracePanel extends Component
};
}
/**
* `componentDidMount` is called when opening the StackTracePanel
* for the first time
*/
componentDidMount() {
- this.maybeFetchStackTrace(this.props);
+ let { request, connector } = this.props;
+ fetchNetworkUpdatePacket(connector.requestData, request, ["stackTrace"]);
}
/**
* `componentWillReceiveProps` is the only method called when
* switching between two requests while this panel is displayed.
*/
componentWillReceiveProps(nextProps) {
- this.maybeFetchStackTrace(nextProps);
- }
-
- /**
- * When switching to another request, lazily fetch stack-trace
- * from the backend. This Panel will first be empty and then
- * display the content.
- */
- maybeFetchStackTrace(props) {
- // Fetch stack trace only if it's available and not yet
- // on the client.
- if (!props.request.stacktrace &&
- props.request.cause.stacktraceAvailable) {
- // This method will set `props.request.stacktrace`
- // asynchronously and force another render.
- props.connector.requestData(props.request.id, "stackTrace");
- }
+ let { request, connector } = nextProps;
+ fetchNetworkUpdatePacket(connector.requestData, request, ["stackTrace"]);
}
// Rendering
render() {
let {
connector,
openLink,
--- a/devtools/client/netmonitor/src/components/StatisticsPanel.js
+++ b/devtools/client/netmonitor/src/components/StatisticsPanel.js
@@ -12,16 +12,17 @@ const PropTypes = require("devtools/clie
const { connect } = require("devtools/client/shared/vendor/react-redux");
const { Chart } = require("devtools/client/shared/widgets/Chart");
const { PluralForm } = require("devtools/shared/plural-form");
const Actions = require("../actions/index");
const { Filters } = require("../utils/filter-predicates");
const { getSizeWithDecimals, getTimeWithDecimals } = require("../utils/format-utils");
const { L10N } = require("../utils/l10n");
const { getPerformanceAnalysisURL } = require("../utils/mdn-utils");
+const { fetchNetworkUpdatePacket } = require("../utils/request-utils");
// Components
const MDNLink = createFactory(require("./MdnLink"));
const { button, div } = dom;
const MediaQueryList = window.matchMedia("(min-width: 700px)");
const NETWORK_ANALYSIS_PIE_CHART_DIAMETER = 200;
@@ -58,16 +59,30 @@ class StatisticsPanel extends Component
this.responseIsFresh = this.responseIsFresh.bind(this);
this.onLayoutChange = this.onLayoutChange.bind(this);
}
componentWillMount() {
this.mdnLinkContainerNodes = new Map();
}
+ componentDidMount() {
+ let { requests, connector } = this.props;
+ requests.forEach((request) => {
+ fetchNetworkUpdatePacket(connector.requestData, request, ["responseHeaders"]);
+ });
+ }
+
+ componentWillReceiveProps(nextProps) {
+ let { requests, connector } = nextProps;
+ requests.forEach((request) => {
+ fetchNetworkUpdatePacket(connector.requestData, request, ["responseHeaders"]);
+ });
+ }
+
componentDidUpdate(prevProps) {
MediaQueryList.addListener(this.onLayoutChange);
const { requests } = this.props;
let ready = requests && requests.length && requests.every((req) =>
req.contentSize !== undefined && req.mimeType && req.responseHeaders &&
req.status !== undefined && req.totalTime !== undefined
);
--- a/devtools/client/netmonitor/src/utils/request-utils.js
+++ b/devtools/client/netmonitor/src/utils/request-utils.js
@@ -65,16 +65,40 @@ async function getFormDataSections(heade
async function fetchHeaders(headers, getLongString) {
for (let { value } of headers.headers) {
headers.headers.value = await getLongString(value);
}
return headers;
}
/**
+ * Fetch network event update packets from actor server
+ * Expect to fetch a couple of network update packets from a given request.
+ *
+ * @param {function} requestData - requestData function for lazily fetch data
+ * @param {object} request - request object
+ * @param {array} updateTypes - a list of network event update types
+ */
+function fetchNetworkUpdatePacket(requestData, request, updateTypes) {
+ updateTypes.forEach((updateType) => {
+ // Only stackTrace will be handled differently
+ if (updateType === "stackTrace") {
+ if (request.cause.stacktraceAvailable && !request.stacktrace) {
+ requestData(request.id, updateType);
+ }
+ return;
+ }
+
+ if (request[`${updateType}Available`] && !request[updateType]) {
+ requestData(request.id, updateType);
+ }
+ });
+}
+
+/**
* Form a data: URI given a mime type, encoding, and some text.
*
* @param {string} mimeType - mime type
* @param {string} encoding - encoding to use; if not set, the
* text will be base64-encoded.
* @param {string} text - text of the URI.
* @return {string} a data URI
*/
@@ -455,16 +479,17 @@ function processNetworkUpdates(request)
}
return result;
}
module.exports = {
decodeUnicodeBase64,
getFormDataSections,
fetchHeaders,
+ fetchNetworkUpdatePacket,
formDataURI,
writeHeaderText,
decodeUnicodeUrl,
getAbbreviatedMimeType,
getEndTime,
getFormattedProtocol,
getResponseHeader,
getResponseTime,