--- a/devtools/client/netmonitor/src/components/RequestListContent.js
+++ b/devtools/client/netmonitor/src/components/RequestListContent.js
@@ -237,16 +237,17 @@ class RequestListContent extends Compone
connector,
columns,
displayedRequests,
firstRequestStartedMillis,
onCauseBadgeMouseDown,
onItemMouseDown,
onSecurityIconMouseDown,
onWaterfallMouseDown,
+ requestFilterTypes,
scale,
selectedRequest,
} = this.props;
return (
div({ className: "requests-list-wrapper" },
div({ className: "requests-list-table" },
div({
@@ -267,16 +268,17 @@ class RequestListContent extends Compone
isSelected: item.id === (selectedRequest && selectedRequest.id),
key: item.id,
onContextMenu: this.onContextMenu,
onFocusedNodeChange: this.onFocusedNodeChange,
onMouseDown: () => onItemMouseDown(item.id),
onCauseBadgeMouseDown: () => onCauseBadgeMouseDown(item.cause),
onSecurityIconMouseDown: () => onSecurityIconMouseDown(item.securityState),
onWaterfallMouseDown: () => onWaterfallMouseDown(),
+ requestFilterTypes,
}))
)
)
)
);
}
}
--- a/devtools/client/netmonitor/src/components/RequestListItem.js
+++ b/devtools/client/netmonitor/src/components/RequestListItem.js
@@ -2,17 +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 { 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 { propertiesEqual } = require("../utils/request-utils");
+const {
+ fetchNetworkUpdatePacket,
+ propertiesEqual,
+} = require("../utils/request-utils");
const { RESPONSE_HEADERS } = require("../constants");
// Components
const RequestListColumnCause = createFactory(require("./RequestListColumnCause"));
const RequestListColumnContentSize = createFactory(require("./RequestListColumnContentSize"));
const RequestListColumnCookies = createFactory(require("./RequestListColumnCookies"));
const RequestListColumnDomain = createFactory(require("./RequestListColumnDomain"));
const RequestListColumnDuration = createFactory(require("./RequestListColumnDuration"));
@@ -52,23 +55,26 @@ const UPDATED_REQ_ITEM_PROPS = [
"url",
"remoteAddress",
"cause",
"contentSize",
"transferredSize",
"startedMillis",
"totalTime",
"requestCookies",
+ "requestHeaders",
"responseCookies",
+ "responseHeaders",
];
const UPDATED_REQ_PROPS = [
"firstRequestStartedMillis",
"index",
"isSelected",
+ "requestFilterTypes",
"waterfallWidth",
];
/**
* Render one row in the request list.
*/
class RequestListItem extends Component {
static get propTypes() {
@@ -81,24 +87,45 @@ class RequestListItem extends Component
firstRequestStartedMillis: PropTypes.number.isRequired,
fromCache: PropTypes.bool,
onCauseBadgeMouseDown: PropTypes.func.isRequired,
onContextMenu: PropTypes.func.isRequired,
onFocusedNodeChange: PropTypes.func,
onMouseDown: PropTypes.func.isRequired,
onSecurityIconMouseDown: PropTypes.func.isRequired,
onWaterfallMouseDown: PropTypes.func.isRequired,
+ requestFilterTypes: PropTypes.string.isRequired,
waterfallWidth: PropTypes.number,
};
}
componentDidMount() {
if (this.props.isSelected) {
this.refs.listItem.focus();
}
+
+ let { connector, item, requestFilterTypes } = this.props;
+ // Filtering XHR & WS require to lazily fetch requestHeaders & responseHeaders
+ if (requestFilterTypes.get("xhr") || requestFilterTypes.get("ws")) {
+ fetchNetworkUpdatePacket(connector.requestData, item, [
+ "requestHeaders",
+ "responseHeaders",
+ ]);
+ }
+ }
+
+ componentWillReceiveProps(nextProps) {
+ let { connector, item, requestFilterTypes } = nextProps;
+ // Filtering XHR & WS require to lazily fetch requestHeaders & responseHeaders
+ if (requestFilterTypes.get("xhr") || requestFilterTypes.get("ws")) {
+ fetchNetworkUpdatePacket(connector.requestData, item, [
+ "requestHeaders",
+ "responseHeaders",
+ ]);
+ }
}
shouldComponentUpdate(nextProps) {
return !propertiesEqual(UPDATED_REQ_ITEM_PROPS, this.props.item, nextProps.item) ||
!propertiesEqual(UPDATED_REQ_PROPS, this.props, nextProps) ||
this.props.columns !== nextProps.columns;
}
--- a/devtools/client/netmonitor/src/components/StackTracePanel.js
+++ b/devtools/client/netmonitor/src/components/StackTracePanel.js
@@ -41,18 +41,16 @@ class StackTracePanel extends Component
* `componentWillReceiveProps` is the only method called when
* switching between two requests while this panel is displayed.
*/
componentWillReceiveProps(nextProps) {
let { request, connector } = nextProps;
fetchNetworkUpdatePacket(connector.requestData, request, ["stackTrace"]);
}
- // Rendering
-
render() {
let {
connector,
openLink,
request,
sourceMapService,
} = this.props;
--- a/devtools/client/netmonitor/src/components/Toolbar.js
+++ b/devtools/client/netmonitor/src/components/Toolbar.js
@@ -13,19 +13,19 @@ const I = require("devtools/client/share
const Actions = require("../actions/index");
const { FILTER_SEARCH_DELAY, FILTER_TAGS } = require("../constants");
const {
getRecordingState,
getTypeFilteredRequests,
isNetworkDetailsToggleButtonDisabled,
} = require("../selectors/index");
-
const { autocompleteProvider } = require("../utils/filter-autocomplete-provider");
const { L10N } = require("../utils/l10n");
+const { fetchNetworkUpdatePacket } = require("../utils/request-utils");
// Components
const SearchBox = createFactory(require("devtools/client/shared/components/SearchBox"));
const { button, div, input, label, span } = dom;
// Localization
const COLLAPSE_DETAILS_PANE = L10N.getStr("collapseDetailsPane");
@@ -130,19 +130,22 @@ class Toolbar extends Component {
autocompleteProvider(filter) {
return autocompleteProvider(filter, this.props.filteredRequests);
}
onSearchBoxFocus() {
let { connector, filteredRequests } = this.props;
- // Fetch responseCookies for building autocomplete list
+ // Fetch responseCookies & responseHeaders for building autocomplete list
filteredRequests.forEach((request) => {
- connector.requestData(request.id, "responseCookies");
+ fetchNetworkUpdatePacket(connector.requestData, request, [
+ "responseCookies",
+ "responseHeaders",
+ ]);
});
}
render() {
let {
toggleRecording,
clearRequests,
requestFilterTypes,
--- a/devtools/client/netmonitor/src/connector/firefox-connector.js
+++ b/devtools/client/netmonitor/src/connector/firefox-connector.js
@@ -66,26 +66,28 @@ class FirefoxConnector {
}
async disconnect() {
this.actions.batchReset();
this.removeListeners();
if (this.tabTarget) {
+ // Unregister `will-navigate` needs to be done before `this.timelineFront.destroy()`
+ // since this.tabTarget might be nullified after timelineFront.destroy().
+ this.tabTarget.off("will-navigate");
// The timeline front wasn't initialized and started if the server wasn't
// recent enough to emit the markers we were interested in.
if (this.tabTarget.getTrait("documentLoadingMarkers") && this.timelineFront) {
this.timelineFront.off("doc-loading", this.onDocLoadingMarker);
await this.timelineFront.destroy();
}
-
- this.tabTarget.off("will-navigate");
this.tabTarget = null;
}
+
this.webConsoleClient = null;
this.timelineFront = null;
this.dataProvider = null;
this.panel = null;
}
pause() {
this.removeListeners();
--- a/devtools/client/netmonitor/src/connector/firefox-data-provider.js
+++ b/devtools/client/netmonitor/src/connector/firefox-data-provider.js
@@ -19,26 +19,24 @@ const { fetchHeaders } = require("../uti
*/
class FirefoxDataProvider {
constructor({webConsoleClient, actions}) {
// Options
this.webConsoleClient = webConsoleClient;
this.actions = actions;
// Internal properties
- this.payloadQueue = [];
- this.rdpRequestMap = new Map();
+ this.payloadQueue = new Map();
// Map[key string => Promise] used by `requestData` to prevent requesting the same
// request data twice.
this.lazyRequestData = new Map();
// Fetching data from the backend
this.getLongString = this.getLongString.bind(this);
- this.getRequestFromQueue = this.getRequestFromQueue.bind(this);
// Event handlers
this.onNetworkEvent = this.onNetworkEvent.bind(this);
this.onNetworkEventUpdate = this.onNetworkEventUpdate.bind(this);
}
/**
* Add a new network request to application state.
@@ -67,33 +65,31 @@ class FirefoxDataProvider {
cause,
// Compatibility code to support Firefox 58 and earlier that always
// send stack-trace immediately on networkEvent message.
// FF59+ supports fetching the traces lazily via requestData.
stacktrace: cause.stacktrace,
fromCache,
- fromServiceWorker},
- true,
- );
+ fromServiceWorker,
+ }, true);
}
emit(EVENTS.REQUEST_ADDED, id);
}
/**
* Update a network request if it already exists in application state.
*
* @param {string} id request id
* @param {object} data data payload will be updated to application state
*/
async updateRequest(id, data) {
let {
- mimeType,
responseContent,
responseCookies,
responseHeaders,
requestCookies,
requestHeaders,
requestPostData,
} = data;
@@ -101,17 +97,17 @@ class FirefoxDataProvider {
let [
responseContentObj,
requestHeadersObj,
responseHeadersObj,
postDataObj,
requestCookiesObj,
responseCookiesObj,
] = await Promise.all([
- this.fetchResponseContent(mimeType, responseContent),
+ this.fetchResponseContent(responseContent),
this.fetchRequestHeaders(requestHeaders),
this.fetchResponseHeaders(responseHeaders),
this.fetchPostData(requestPostData),
this.fetchRequestCookies(requestCookies),
this.fetchResponseCookies(responseCookies),
]);
let payload = Object.assign({},
@@ -119,50 +115,64 @@ class FirefoxDataProvider {
responseContentObj,
requestHeadersObj,
responseHeadersObj,
postDataObj,
requestCookiesObj,
responseCookiesObj
);
- this.pushRequestToQueue(id, payload);
+ if (this.actions.updateRequest) {
+ await this.actions.updateRequest(id, payload, true);
+ }
return payload;
}
- async fetchResponseContent(mimeType, responseContent) {
+ async fetchResponseContent(responseContent) {
let payload = {};
- if (mimeType && responseContent && responseContent.content) {
+ if (responseContent && responseContent.content) {
let { text } = responseContent.content;
let response = await this.getLongString(text);
responseContent.content.text = response;
payload.responseContent = responseContent;
+
+ // Lock down responseContentAvailable once we fetch data from back-end.
+ // Using this as flag to prevent fetching arrived data again.
+ payload.responseContentAvailable = false;
}
return payload;
}
async fetchRequestHeaders(requestHeaders) {
let payload = {};
if (requestHeaders && requestHeaders.headers && requestHeaders.headers.length) {
let headers = await fetchHeaders(requestHeaders, this.getLongString);
if (headers) {
payload.requestHeaders = headers;
}
+
+ // Lock down requestHeadersAvailable once we fetch data from back-end.
+ // Using this as flag to prevent fetching arrived data again.
+ payload.requestHeadersAvailable = false;
}
return payload;
}
async fetchResponseHeaders(responseHeaders) {
let payload = {};
if (responseHeaders && responseHeaders.headers && responseHeaders.headers.length) {
let headers = await fetchHeaders(responseHeaders, this.getLongString);
if (headers) {
payload.responseHeaders = headers;
}
+
+ // Lock down responseHeadersAvailable once we fetch data from back-end.
+ // Using this as flag to prevent fetching arrived data again.
+ payload.responseHeadersAvailable = false;
}
return payload;
}
async fetchPostData(requestPostData) {
let payload = {};
if (requestPostData && requestPostData.postData) {
let { text } = requestPostData.postData;
@@ -181,16 +191,42 @@ class FirefoxDataProvider {
// Lock down requestPostDataAvailable once we fetch data from back-end.
// Using this as flag to prevent fetching arrived data again.
payload.requestPostDataAvailable = false;
}
return payload;
}
+ async fetchRequestCookies(requestCookies) {
+ let payload = {};
+ 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 this.getLongString(cookie.value),
+ }));
+ }
+ if (reqCookies.length) {
+ payload.requestCookies = reqCookies;
+ }
+ }
+
+ // Lock down requestCookiesAvailable once we fetch data from back-end.
+ // Using this as flag to prevent fetching arrived data again.
+ payload.requestCookiesAvailable = false;
+ }
+ return payload;
+ }
+
async fetchResponseCookies(responseCookies) {
let payload = {};
if (responseCookies) {
let resCookies = [];
// response store cookies in responseCookies or responseCookies.cookies
let cookies = responseCookies.cookies ?
responseCookies.cookies : responseCookies;
// make sure cookies is iterable
@@ -207,103 +243,38 @@ class FirefoxDataProvider {
// Lock down responseCookiesAvailable once we fetch data from back-end.
// Using this as flag to prevent fetching arrived data again.
payload.responseCookiesAvailable = false;
}
return payload;
}
- async fetchRequestCookies(requestCookies) {
- let payload = {};
- 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 this.getLongString(cookie.value),
- }));
- }
- if (reqCookies.length) {
- payload.requestCookies = reqCookies;
- }
- }
-
- // Lock down requestCookiesAvailable once we fetch data from back-end.
- // Using this as flag to prevent fetching arrived data again.
- payload.requestCookiesAvailable = false;
- }
- return payload;
- }
-
- /**
- * Access a payload item from payload queue.
- *
- * @param {string} id request id
- * @return {boolean} return a queued payload item from queue.
- */
- getRequestFromQueue(id) {
- return this.payloadQueue.find((item) => item.id === id);
- }
-
/**
* Public API used by the Toolbox: Tells if there is still any pending request.
*
* @return {boolean} returns true if the payload queue is empty
*/
isPayloadQueueEmpty() {
- return this.payloadQueue.length === 0;
- }
-
- /**
- * Return true if payload is ready (all data fetched from the backend)
- *
- * @param {string} id request id
- * @return {boolean} return whether a specific networkEvent has been updated completely.
- */
- isRequestPayloadReady(id) {
- let record = this.rdpRequestMap.get(id);
- if (!record) {
- return false;
- }
-
- let { payload } = this.getRequestFromQueue(id);
-
- // The payload is ready when all values in the record are true.
- // Note that we never fetch response header/cookies for request with security issues.
- // Bug 1404917 should simplify this heuristic by making all these field be lazily
- // fetched, only on-demand.
- return record.requestHeaders && record.eventTimings &&
- (record.responseHeaders || payload.securityState === "broken" ||
- (!payload.status && payload.responseContentAvailable));
+ return this.payloadQueue.size === 0;
}
/**
* Merge upcoming networkEventUpdate payload into existing one.
*
- * @param {string} id request id
+ * @param {string} id request actor id
* @param {object} payload request data payload
*/
pushRequestToQueue(id, payload) {
- let request = this.getRequestFromQueue(id);
- if (!request) {
- this.payloadQueue.push({ id, payload });
- } else {
- // Merge upcoming networkEventUpdate payload into existing one
- request.payload = Object.assign({}, request.payload, payload);
+ let payloadFromQueue = this.payloadQueue.get(id);
+ if (!payloadFromQueue) {
+ payloadFromQueue = {};
+ this.payloadQueue.set(id, payloadFromQueue);
}
- }
-
- cleanUpQueue(id) {
- this.payloadQueue = this.payloadQueue.filter(
- request => request.id != id);
+ Object.assign(payloadFromQueue, payload);
}
/**
* Fetches the network information packet from actor server
*
* @param {string} id request id
* @return {object} networkInfo data packet
*/
@@ -327,38 +298,31 @@ class FirefoxDataProvider {
}
/**
* The "networkEvent" message type handler.
*
* @param {string} type message type
* @param {object} networkInfo network request information
*/
- onNetworkEvent(type, networkInfo) {
+ async onNetworkEvent(type, networkInfo) {
let {
actor,
cause,
fromCache,
fromServiceWorker,
isXHR,
request: {
method,
url,
},
startedDateTime,
} = networkInfo;
- // Create tracking record for this request.
- this.rdpRequestMap.set(actor, {
- requestHeaders: false,
- responseHeaders: false,
- eventTimings: false,
- });
-
- this.addRequest(actor, {
+ await this.addRequest(actor, {
cause,
fromCache,
fromServiceWorker,
isXHR,
method,
startedDateTime,
url,
});
@@ -368,126 +332,82 @@ class FirefoxDataProvider {
/**
* The "networkEventUpdate" message type handler.
*
* @param {string} type message type
* @param {object} packet the message received from the server.
* @param {object} networkInfo the network request information.
*/
- onNetworkEventUpdate(type, data) {
+ async onNetworkEventUpdate(type, data) {
let { packet, networkInfo } = data;
let { actor } = networkInfo;
let { updateType } = packet;
- // When we pause and resume, we may receive `networkEventUpdate` for a request
- // that started during the pause and we missed its `networkEvent`.
- if (!this.rdpRequestMap.has(actor)) {
- return;
- }
-
switch (updateType) {
- case "requestHeaders":
- case "responseHeaders":
- this.requestPayloadData(actor, updateType);
- break;
- case "requestCookies":
- case "responseCookies":
- case "requestPostData":
- // This field helps knowing when/if updateType property is available
- // and can be requested via `requestData`
- this.updateRequest(actor, { [`${updateType}Available`]: true });
- break;
case "securityInfo":
- this.updateRequest(actor, { securityState: networkInfo.securityInfo });
+ this.pushRequestToQueue(actor, { securityState: networkInfo.securityInfo });
break;
case "responseStart":
- this.updateRequest(actor, {
+ this.pushRequestToQueue(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);
});
+ emit(EVENTS.STARTED_RECEIVING_RESPONSE, actor);
break;
case "responseContent":
- this.updateRequest(actor, {
+ this.pushRequestToQueue(actor, {
contentSize: networkInfo.response.bodySize,
transferredSize: networkInfo.response.transferredSize,
mimeType: networkInfo.response.content.mimeType,
- // This field helps knowing when/if responseContent property is available
- // and can be requested via `requestData`
- responseContentAvailable: true,
});
break;
case "eventTimings":
this.pushRequestToQueue(actor, { totalTime: networkInfo.totalTime });
- this.requestPayloadData(actor, updateType);
+ await this._requestData(actor, updateType);
break;
}
+ // This available field helps knowing when/if updateType property is arrived
+ // and can be requested via `requestData`
+ this.pushRequestToQueue(actor, { [`${updateType}Available`]: true });
+
+ this.onPayloadDataReceived(actor);
+
emit(EVENTS.NETWORK_EVENT_UPDATED, actor);
}
/**
- * Wrapper method for requesting HTTP details data for the payload.
- *
- * It is specific to all requests done from `onNetworkEventUpdate`, for data that are
- * immediately fetched whenever the data is available.
- *
- * All these requests are cached into `rdpRequestMap`. All requests related to a given
- * actor will be collected in the same record.
- *
- * Once bug 1404917 is completed, we should no longer use this method.
- * All request fields should be loaded only on-demand, via `requestData` method.
- *
- * @param {string} actor actor id (used as request id)
- * @param {string} method identifier of the data we want to fetch
+ * Notify actions when messages from onNetworkEventUpdate are done, networkEventUpdate
+ * messages contain initial network info for each updateType and then we can invoke
+ * requestData to fetch its corresponded data lazily.
+ * Once all updateTypes of networkEventUpdate message are arrived, we flush merged
+ * request payload from pending queue and then update component.
*/
- requestPayloadData(actor, method) {
- let record = this.rdpRequestMap.get(actor);
+ async onPayloadDataReceived(actor) {
+ let payload = this.payloadQueue.get(actor) || {};
- // If data has been already requested, do nothing.
- if (record[method]) {
+ if (!payload.requestHeadersAvailable || !payload.requestCookiesAvailable ||
+ !payload.eventTimingsAvailable || !payload.responseContentAvailable) {
return;
}
- let promise = this._requestData(actor, method);
- promise.then(() => {
- // Once we got the data toggle the Map item to `true` in order to
- // make isRequestPayloadReady return `true` once all the data is fetched.
- record[method] = true;
- this.onPayloadDataReceived(actor, method, !record);
- });
- }
+ this.payloadQueue.delete(actor);
- /**
- * Executed when new data are received from the backend.
- */
- async onPayloadDataReceived(actor, type) {
- // Notify actions when all the sync request from onNetworkEventUpdate are done,
- // or, everytime requestData is called for fetching data lazily.
- if (this.isRequestPayloadReady(actor)) {
- let payloadFromQueue = this.getRequestFromQueue(actor).payload;
+ if (this.actions.updateRequest) {
+ await this.actions.updateRequest(actor, payload, true);
+ }
- // Clean up
- this.cleanUpQueue(actor);
- this.rdpRequestMap.delete(actor);
-
- if (this.actions.updateRequest) {
- await this.actions.updateRequest(actor, payloadFromQueue, true);
- }
-
- // This event is fired only once per request, once all the properties are fetched
- // from `onNetworkEventUpdate`. There should be no more RDP requests after this.
- emit(EVENTS.PAYLOAD_READY, actor);
- }
+ // This event is fired only once per request, once all the properties are fetched
+ // from `onNetworkEventUpdate`. There should be no more RDP requests after this.
+ emit(EVENTS.PAYLOAD_READY, actor);
}
/**
* Public connector API to lazily request HTTP details from the backend.
*
* The method focus on:
* - calling the right actor method,
* - emitting an event to tell we start fetching some request data,
@@ -503,31 +423,30 @@ class FirefoxDataProvider {
// the same data twice at the same time.
let key = `${actor}-${method}`;
let promise = this.lazyRequestData.get(key);
// If a request is pending, reuse it.
if (promise) {
return promise;
}
// Fetch the data
- promise = this._requestData(actor, method);
- this.lazyRequestData.set(key, promise);
- promise.then(async () => {
+ promise = this._requestData(actor, method).then(async (payload) => {
// Remove the request from the cache, any new call to requestData will fetch the
// data again.
- this.lazyRequestData.delete(key, promise);
+ this.lazyRequestData.delete(key);
if (this.actions.updateRequest) {
- await this.actions.updateRequest(
- actor,
- this.getRequestFromQueue(actor).payload,
- true,
- );
+ await this.actions.updateRequest(actor, payload, true);
}
+
+ return payload;
});
+
+ this.lazyRequestData.set(key, promise);
+
return promise;
}
/**
* Internal helper used to request HTTP details from the backend.
*
* This is internal method that focus on:
* - calling the right actor method,
@@ -552,17 +471,17 @@ class FirefoxDataProvider {
let response = await new Promise((resolve, reject) => {
// Do a RDP request to fetch data from the actor.
if (typeof this.webConsoleClient[clientMethodName] === "function") {
// Make sure we fetch the real actor data instead of cloned actor
// e.g. CustomRequestPanel will clone a request with additional '-clone' actor id
this.webConsoleClient[clientMethodName](actor.replace("-clone", ""), (res) => {
if (res.error) {
- console.error(res.message);
+ reject(new Error(res.message));
}
resolve(res);
});
} else {
reject(new Error(`Error: No such client method '${clientMethodName}'!`));
}
});
@@ -576,22 +495,35 @@ class FirefoxDataProvider {
return this[callbackMethodName](response);
}
/**
* Handles additional information received for a "requestHeaders" packet.
*
* @param {object} response the message received from the server.
*/
- onRequestHeaders(response) {
- return this.updateRequest(response.from, {
+ async onRequestHeaders(response) {
+ let payload = await this.updateRequest(response.from, {
requestHeaders: response
- }).then(() => {
- emit(EVENTS.RECEIVED_REQUEST_HEADERS, response.from);
});
+ emit(EVENTS.RECEIVED_REQUEST_HEADERS, response.from);
+ return payload.requestHeaders;
+ }
+
+ /**
+ * Handles additional information received for a "responseHeaders" packet.
+ *
+ * @param {object} response the message received from the server.
+ */
+ async onResponseHeaders(response) {
+ let payload = await this.updateRequest(response.from, {
+ responseHeaders: response
+ });
+ emit(EVENTS.RECEIVED_RESPONSE_HEADERS, response.from);
+ return payload.responseHeaders;
}
/**
* Handles additional information received for a "requestCookies" packet.
*
* @param {object} response the message received from the server.
*/
async onRequestCookies(response) {
@@ -615,35 +547,22 @@ class FirefoxDataProvider {
return payload;
}
/**
* Handles additional information received for a "securityInfo" packet.
*
* @param {object} response the message received from the server.
*/
- onSecurityInfo(response) {
- return this.updateRequest(response.from, {
+ async onSecurityInfo(response) {
+ let payload = await this.updateRequest(response.from, {
securityInfo: response.securityInfo
- }).then(() => {
- emit(EVENTS.RECEIVED_SECURITY_INFO, response.from);
});
- }
-
- /**
- * Handles additional information received for a "responseHeaders" packet.
- *
- * @param {object} response the message received from the server.
- */
- onResponseHeaders(response) {
- return this.updateRequest(response.from, {
- responseHeaders: response
- }).then(() => {
- emit(EVENTS.RECEIVED_RESPONSE_HEADERS, response.from);
- });
+ emit(EVENTS.RECEIVED_SECURITY_INFO, response.from);
+ return payload.securityInfo;
}
/**
* Handles additional information received for a "responseCookies" packet.
*
* @param {object} response the message received from the server.
*/
async onResponseCookies(response) {
@@ -671,22 +590,22 @@ class FirefoxDataProvider {
return payload.responseContent;
}
/**
* Handles additional information received for a "eventTimings" packet.
*
* @param {object} response the message received from the server.
*/
- onEventTimings(response) {
- return this.updateRequest(response.from, {
+ async onEventTimings(response) {
+ let payload = await this.updateRequest(response.from, {
eventTimings: response
- }).then(() => {
- emit(EVENTS.RECEIVED_EVENT_TIMINGS, response.from);
});
+ emit(EVENTS.RECEIVED_EVENT_TIMINGS, response.from);
+ return payload.eventTimings;
}
/**
* Handles information received for a "stackTrace" packet.
*
* @param {object} response the message received from the server.
*/
async onStackTrace(response) {
--- a/devtools/client/netmonitor/src/constants.js
+++ b/devtools/client/netmonitor/src/constants.js
@@ -68,18 +68,18 @@ const EVENTS = {
UPDATING_REQUEST_COOKIES: "NetMonitor:NetworkEventUpdating:RequestCookies",
RECEIVED_REQUEST_COOKIES: "NetMonitor:NetworkEventUpdated:RequestCookies",
// When request post data begins and finishes receiving.
UPDATING_REQUEST_POST_DATA: "NetMonitor:NetworkEventUpdating:RequestPostData",
RECEIVED_REQUEST_POST_DATA: "NetMonitor:NetworkEventUpdated:RequestPostData",
// When security information begins and finishes receiving.
- UPDATING_SECURITY_INFO: "NetMonitor::NetworkEventUpdating:SecurityInfo",
- RECEIVED_SECURITY_INFO: "NetMonitor::NetworkEventUpdated:SecurityInfo",
+ UPDATING_SECURITY_INFO: "NetMonitor:NetworkEventUpdating:SecurityInfo",
+ RECEIVED_SECURITY_INFO: "NetMonitor:NetworkEventUpdated:SecurityInfo",
// When response headers begin and finish receiving.
UPDATING_RESPONSE_HEADERS: "NetMonitor:NetworkEventUpdating:ResponseHeaders",
RECEIVED_RESPONSE_HEADERS: "NetMonitor:NetworkEventUpdated:ResponseHeaders",
// When response cookies begin and finish receiving.
UPDATING_RESPONSE_COOKIES: "NetMonitor:NetworkEventUpdating:ResponseCookies",
RECEIVED_RESPONSE_COOKIES: "NetMonitor:NetworkEventUpdated:ResponseCookies",
@@ -108,30 +108,33 @@ const UPDATE_PROPS = [
"url",
"remotePort",
"remoteAddress",
"status",
"statusText",
"httpVersion",
"securityState",
"securityInfo",
+ "securityInfoAvailable",
"mimeType",
"contentSize",
"transferredSize",
"totalTime",
"eventTimings",
"headersSize",
"customQueryValue",
"requestHeaders",
+ "requestHeadersAvailable",
"requestHeadersFromUploadStream",
"requestCookies",
"requestCookiesAvailable",
"requestPostData",
"requestPostDataAvailable",
"responseHeaders",
+ "responseHeadersAvailable",
"responseCookies",
"responseCookiesAvailable",
"responseContent",
"responseContentAvailable",
"formDataSections",
"stacktrace",
];
--- a/devtools/client/netmonitor/src/har/har-builder.js
+++ b/devtools/client/netmonitor/src/har/har-builder.js
@@ -148,28 +148,41 @@ HarBuilder.prototype = {
onContentLoad: -1,
onLoad: -1
};
return timings;
},
buildRequest: async function (file) {
+ // When using HarAutomation, HarCollector will automatically fetch requestHeaders
+ // and requestCookies, but when we use it from netmonitor, FirefoxDataProvider
+ // should fetch it itself lazily, via requestData.
+
+ let requestHeaders = file.requestHeaders;
+ if (!requestHeaders && this._options.requestData) {
+ requestHeaders = await this._options.requestData(file.id, "requestHeaders");
+ }
+
+ let requestCookies = file.requestCookies;
+ if (!requestCookies && this._options.requestData) {
+ requestCookies = await this._options.requestData(file.id, "requestCookies");
+ }
+
let request = {
bodySize: 0
};
-
request.method = file.method;
request.url = file.url;
request.httpVersion = file.httpVersion || "";
- request.headers = this.buildHeaders(file.requestHeaders);
+ request.headers = this.buildHeaders(requestHeaders);
request.headers = this.appendHeadersPostData(request.headers, file);
- request.cookies = this.buildCookies(file.requestCookies);
+ request.cookies = this.buildCookies(requestCookies);
request.queryString = parseQueryString(getUrlQuery(file.url)) || [];
- request.headersSize = file.requestHeaders.headersSize;
+ request.headersSize = requestHeaders.headersSize;
request.postData = await this.buildPostData(file);
if (request.postData && request.postData.text) {
request.bodySize = request.postData.text.length;
}
return request;
},
@@ -229,33 +242,37 @@ HarBuilder.prototype = {
});
});
});
return result;
},
buildPostData: async function (file) {
- // When using HarAutomation, HarCollector will automatically fetch requestPostData,
- // but when we use it from netmonitor, FirefoxDataProvider should fetch it itself
- // lazily, via requestData.
+ // When using HarAutomation, HarCollector will automatically fetch requestPostData
+ // and requestHeaders, but when we use it from netmonitor, FirefoxDataProvider
+ // should fetch it itself lazily, via requestData.
let requestPostData = file.requestPostData;
let requestHeaders = file.requestHeaders;
let requestHeadersFromUploadStream;
if (!requestPostData && this._options.requestData) {
let payload = await this._options.requestData(file.id, "requestPostData");
requestPostData = payload.requestPostData;
requestHeadersFromUploadStream = payload.requestHeadersFromUploadStream;
}
if (!requestPostData.postData.text) {
return undefined;
}
+ if (!requestHeaders && this._options.requestData) {
+ requestHeaders = await this._options.requestData(file.id, "requestHeaders");
+ }
+
let postData = {
mimeType: findValue(requestHeaders.headers, "content-type"),
params: [],
text: requestPostData.postData.text,
};
if (requestPostData.postDataDiscarded) {
postData.comment = L10N.getStr("har.requestBodyNotIncluded");
@@ -283,32 +300,43 @@ HarBuilder.prototype = {
}
});
}
return postData;
},
buildResponse: async function (file) {
+ // When using HarAutomation, HarCollector will automatically fetch responseHeaders
+ // and responseCookies, but when we use it from netmonitor, FirefoxDataProvider
+ // should fetch it itself lazily, via requestData.
+
+ let responseHeaders = file.responseHeaders;
+ if (!responseHeaders && this._options.requestData) {
+ responseHeaders = await this._options.requestData(file.id, "responseHeaders");
+ }
+
+ let responseCookies = file.responseCookies;
+ if (!responseCookies && this._options.requestData) {
+ responseCookies = await this._options.requestData(file.id, "responseCookies");
+ }
+
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.cookies = this.buildCookies(responseCookies);
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;
--- a/devtools/client/netmonitor/src/har/test/browser.ini
+++ b/devtools/client/netmonitor/src/har/test/browser.ini
@@ -2,15 +2,14 @@
tags = devtools
subsuite = clipboard
skip-if = (os == 'linux' && bits == 32 && debug) # bug 1328915, disable linux32 debug devtools for timeouts
support-files =
head.js
html_har_post-data-test-page.html
!/devtools/client/netmonitor/test/head.js
!/devtools/client/framework/test/shared-head.js
- !/devtools/client/netmonitor/test/shared-head.js
!/devtools/client/netmonitor/test/html_simple-test-page.html
[browser_net_har_copy_all_as_har.js]
[browser_net_har_post_data.js]
[browser_net_har_throttle_upload.js]
[browser_net_har_post_data_on_get.js]
--- 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
@@ -42,21 +42,23 @@ function* throttleUploadTest(actuallyThr
info("sending throttle request");
yield new Promise((resolve) => {
connector.setPreferences(request, (response) => {
resolve(response);
});
});
// Execute one POST request on the page and wait till its done.
+ let onEventTimings = monitor.panelWin.once(EVENTS.RECEIVED_EVENT_TIMINGS);
let wait = waitForNetworkEvents(monitor, 1);
yield ContentTask.spawn(tab.linkedBrowser, { size }, function* (args) {
content.wrappedJSObject.executeTest2(args.size);
});
yield wait;
+ yield onEventTimings;
// Copy HAR into the clipboard (asynchronous).
let contextMenu = new RequestListContextMenu({ connector });
let jsonString = yield contextMenu.copyAllAsHar(getSortedRequests(store.getState()));
let har = JSON.parse(jsonString);
// Check out the HAR log.
isnot(har.log, null, "The HAR log must exist");
--- a/devtools/client/netmonitor/src/utils/filter-autocomplete-provider.js
+++ b/devtools/client/netmonitor/src/utils/filter-autocomplete-provider.js
@@ -51,18 +51,18 @@ function getAutocompleteValuesForFlag(fl
values = responseCookies.map(c => c.hasOwnProperty("domain") ?
c.domain : request.urlDetails.host);
break;
case "is":
values = ["cached", "from-cache", "running"];
break;
case "has-response-header":
// Some requests not having responseHeaders..?
- values = request.responseHeaders &&
- request.responseHeaders.headers.map(h => h.name);
+ values = request.responseHeaders ?
+ request.responseHeaders.headers.map(h => h.name) : [];
break;
case "protocol":
values.push(request.httpVersion);
break;
case "method":
default:
values.push(request[flag]);
}
@@ -103,20 +103,21 @@ function getLastTokenFlagValues(lastToke
let values = [];
for (let request of requests) {
values.push(...getAutocompleteValuesForFlag(flag, request));
}
values = [...new Set(values)];
return values
+ .filter(value => value)
.filter(value => {
- if (typedFlagValue) {
- let lowerTyped = typedFlagValue.toLowerCase(),
- lowerValue = value.toLowerCase();
+ if (typedFlagValue && value) {
+ let lowerTyped = typedFlagValue.toLowerCase();
+ let lowerValue = value.toLowerCase();
return lowerValue.includes(lowerTyped) && lowerValue !== lowerTyped;
}
return typeof value !== "undefined" && value !== "" && value !== "undefined";
})
.sort()
.map(value => isNegativeFlag ? `-${flag}:${value}` : `${flag}:${value}`);
}
--- a/devtools/client/netmonitor/src/utils/request-utils.js
+++ b/devtools/client/netmonitor/src/utils/request-utils.js
@@ -415,52 +415,59 @@ function getResponseHeader(item, header)
}
}
return null;
}
/**
* Extracts any urlencoded form data sections from a POST request.
*/
-function updateFormDataSections(props) {
+async function updateFormDataSections(props) {
let {
connector,
request = {},
updateRequest,
} = props;
let {
+ id,
formDataSections,
requestHeaders,
+ requestHeadersAvailable,
requestHeadersFromUploadStream,
requestPostData,
+ requestPostDataAvailable,
} = request;
- if (!formDataSections && requestHeaders &&
- requestHeadersFromUploadStream && requestPostData) {
- getFormDataSections(
+ if (requestHeadersAvailable && !requestHeaders) {
+ requestHeaders = await connector.requestData(id, "requestHeaders");
+ }
+
+ if (requestPostDataAvailable && !requestPostData) {
+ requestPostData = await connector.requestData(id, "requestPostData");
+ }
+
+ if (!formDataSections && requestHeaders && requestPostData &&
+ requestHeadersFromUploadStream) {
+ formDataSections = await getFormDataSections(
requestHeaders,
requestHeadersFromUploadStream,
requestPostData,
connector.getLongString,
- ).then((newFormDataSections) => {
- updateRequest(
- request.id,
- { formDataSections: newFormDataSections },
- true,
- );
- });
+ );
+
+ updateRequest(request.id, { formDataSections }, true);
}
}
/**
* This helper function is used for additional processing of
* incoming network update packets. It's used by Network and
* Console panel reducers.
*/
-function processNetworkUpdates(request) {
+function processNetworkUpdates(request = {}) {
let result = {};
for (let [key, value] of Object.entries(request)) {
if (UPDATE_PROPS.includes(key)) {
result[key] = value;
switch (key) {
case "securityInfo":
result.securityState = value.state;
--- a/devtools/client/netmonitor/src/widgets/RequestListContextMenu.js
+++ b/devtools/client/netmonitor/src/widgets/RequestListContextMenu.js
@@ -29,19 +29,21 @@ class RequestListContextMenu {
let {
id,
isCustom,
formDataSections,
method,
mimeType,
httpVersion,
requestHeaders,
+ requestHeadersAvailable,
requestPostData,
requestPostDataAvailable,
responseHeaders,
+ responseHeadersAvailable,
responseContentAvailable,
url,
} = selectedRequest;
let {
cloneSelectedRequest,
openStatistics,
} = this.props;
let menu = [];
@@ -62,53 +64,63 @@ class RequestListContextMenu {
visible: !!(selectedRequest && getUrlQuery(url)),
click: () => this.copyUrlParams(url),
});
copySubmenu.push({
id: "request-list-context-copy-post-data",
label: L10N.getStr("netmonitor.context.copyPostData"),
accesskey: L10N.getStr("netmonitor.context.copyPostData.accesskey"),
+ // Menu item will be visible even if data hasn't arrived, so we need to check
+ // *Available property and then fetch data lazily once user triggers the action.
visible: !!(selectedRequest && (requestPostDataAvailable || requestPostData)),
click: () => this.copyPostData(id, formDataSections),
});
copySubmenu.push({
id: "request-list-context-copy-as-curl",
label: L10N.getStr("netmonitor.context.copyAsCurl"),
accesskey: L10N.getStr("netmonitor.context.copyAsCurl.accesskey"),
- visible: !!selectedRequest,
+ // Menu item will be visible even if data hasn't arrived, so we need to check
+ // *Available property and then fetch data lazily once user triggers the action.
+ visible: !!(selectedRequest && (requestHeadersAvailable || requestHeaders)),
click: () => this.copyAsCurl(id, url, method, requestHeaders, httpVersion),
});
copySubmenu.push({
type: "separator",
visible: copySubmenu.slice(0, 4).some((subMenu) => subMenu.visible),
});
copySubmenu.push({
id: "request-list-context-copy-request-headers",
label: L10N.getStr("netmonitor.context.copyRequestHeaders"),
accesskey: L10N.getStr("netmonitor.context.copyRequestHeaders.accesskey"),
- visible: !!(selectedRequest && requestHeaders && requestHeaders.rawHeaders),
- click: () => this.copyRequestHeaders(requestHeaders.rawHeaders.trim()),
+ // Menu item will be visible even if data hasn't arrived, so we need to check
+ // *Available property and then fetch data lazily once user triggers the action.
+ visible: !!(selectedRequest && (requestHeadersAvailable || requestHeaders)),
+ click: () => this.copyRequestHeaders(id, requestHeaders),
});
copySubmenu.push({
id: "response-list-context-copy-response-headers",
label: L10N.getStr("netmonitor.context.copyResponseHeaders"),
accesskey: L10N.getStr("netmonitor.context.copyResponseHeaders.accesskey"),
- visible: !!(selectedRequest && responseHeaders && responseHeaders.rawHeaders),
- click: () => this.copyResponseHeaders(responseHeaders.rawHeaders.trim()),
+ // Menu item will be visible even if data hasn't arrived, so we need to check
+ // *Available property and then fetch data lazily once user triggers the action.
+ visible: !!(selectedRequest && (responseHeadersAvailable || responseHeaders)),
+ click: () => this.copyResponseHeaders(id, responseHeaders),
});
copySubmenu.push({
id: "request-list-context-copy-response",
label: L10N.getStr("netmonitor.context.copyResponse"),
accesskey: L10N.getStr("netmonitor.context.copyResponse.accesskey"),
+ // Menu item will be visible even if data hasn't arrived, so we need to check
+ // *Available property and then fetch data lazily once user triggers the action.
visible: !!(selectedRequest && responseContentAvailable),
click: () => this.copyResponse(id),
});
copySubmenu.push({
id: "request-list-context-copy-image-as-data-uri",
label: L10N.getStr("netmonitor.context.copyImageAsDataUri"),
accesskey: L10N.getStr("netmonitor.context.copyImageAsDataUri.accesskey"),
@@ -275,43 +287,56 @@ class RequestListContextMenu {
}
copyString(string);
}
/**
* Copy a cURL command from the currently selected item.
*/
async copyAsCurl(id, url, method, requestHeaders, httpVersion) {
+ if (!requestHeaders) {
+ requestHeaders = await this.props.connector.requestData(id, "requestHeaders");
+ }
let { requestPostData } = await this.props.connector
.requestData(id, "requestPostData");
// Create a sanitized object for the Curl command generator.
let data = {
url,
method,
headers: requestHeaders.headers,
httpVersion: httpVersion,
postDataText: requestPostData ? requestPostData.postData.text : "",
};
copyString(Curl.generateCommand(data));
}
/**
* Copy the raw request headers from the currently selected item.
*/
- copyRequestHeaders(rawHeaders) {
+ async copyRequestHeaders(id, requestHeaders) {
+ if (!requestHeaders) {
+ requestHeaders = await this.props.connector.requestData(id, "requestHeaders");
+ }
+ let rawHeaders = requestHeaders.rawHeaders.trim();
+
if (Services.appinfo.OS !== "WINNT") {
rawHeaders = rawHeaders.replace(/\r/g, "");
}
copyString(rawHeaders);
}
/**
* Copy the raw response headers from the currently selected item.
*/
- copyResponseHeaders(rawHeaders) {
+ async copyResponseHeaders(id, responseHeaders) {
+ if (!responseHeaders) {
+ responseHeaders = await this.props.connector.requestData(id, "responseHeaders");
+ }
+ let rawHeaders = responseHeaders.rawHeaders.trim();
+
if (Services.appinfo.OS !== "WINNT") {
rawHeaders = rawHeaders.replace(/\r/g, "");
}
copyString(rawHeaders);
}
/**
* Copy image as data uri.
--- a/devtools/client/netmonitor/test/browser.ini
+++ b/devtools/client/netmonitor/test/browser.ini
@@ -1,15 +1,14 @@
[DEFAULT]
tags = devtools
subsuite = devtools
support-files =
dropmarker.svg
head.js
- shared-head.js
html_cause-test-page.html
html_content-type-without-cache-test-page.html
html_brotli-test-page.html
html_image-tooltip-test-page.html
html_cors-test-page.html
html_custom-get-page.html
html_cyrillic-test-page.html
html_frame-test-page.html
--- a/devtools/client/netmonitor/test/browser_net_cause_redirect.js
+++ b/devtools/client/netmonitor/test/browser_net_cause_redirect.js
@@ -28,19 +28,21 @@ add_task(function* () {
store.dispatch(Actions.batchEnable(false));
let wait = waitForNetworkEvents(monitor, EXPECTED_REQUESTS.length);
yield performRequests(2, HSTS_SJS);
yield wait;
// Fetch stack-trace data from the backend and wait till
// all packets are received.
- let requests = getSortedRequests(store.getState());
- yield Promise.all(requests.map(requestItem =>
- connector.requestData(requestItem.id, "stackTrace")));
+ let requests = getSortedRequests(store.getState())
+ .filter((req) => !req.stacktrace)
+ .map((req) => connector.requestData(req.id, "stackTrace"));
+
+ yield Promise.all(requests);
EXPECTED_REQUESTS.forEach(({status, hasStack}, i) => {
let item = getSortedRequests(store.getState()).get(i);
is(item.status, status, `Request #${i} has the expected status`);
let { stacktrace } = item;
let stackLen = stacktrace ? stacktrace.length : 0;
--- a/devtools/client/netmonitor/test/browser_net_copy_headers.js
+++ b/devtools/client/netmonitor/test/browser_net_copy_headers.js
@@ -27,18 +27,16 @@ add_task(function* () {
let requestItem = getSortedRequests(store.getState()).get(0);
let { method, httpVersion, status, statusText } = requestItem;
EventUtils.sendMouseEvent({ type: "contextmenu" },
document.querySelectorAll(".request-list-item")[0]);
let selectedRequest = getSelectedRequest(store.getState());
is(selectedRequest, requestItem, "Proper request is selected");
- ok(selectedRequest.requestHeaders, "Selected request should have request headers");
- ok(selectedRequest.responseHeaders, "Selected request should have response headers");
const EXPECTED_REQUEST_HEADERS = [
`${method} ${SIMPLE_URL} ${httpVersion}`,
"Host: example.com",
"User-Agent: " + navigator.userAgent + "",
"Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
"Accept-Language: " + navigator.languages.join(",") + ";q=0.5",
"Accept-Encoding: gzip, deflate",
--- a/devtools/client/netmonitor/test/browser_net_curl-utils.js
+++ b/devtools/client/netmonitor/test/browser_net_curl-utils.js
@@ -230,34 +230,35 @@ function testEscapeStringWin() {
let newLines = "line1\r\nline2\r\nline3";
is(CurlUtils.escapeStringWin(newLines),
'"line1"^\u000d\u000A"line2"^\u000d\u000A"line3"',
"Newlines should be escaped.");
}
function* createCurlData(selected, getLongString, requestData) {
- let { url, method, httpVersion } = selected;
+ let { id, url, method, httpVersion } = selected;
// Create a sanitized object for the Curl command generator.
let data = {
url,
method,
headers: [],
httpVersion,
postDataText: null
};
+ let requestHeaders = yield requestData(id, "requestHeaders");
// Fetch header values.
- for (let { name, value } of selected.requestHeaders.headers) {
+ for (let { name, value } of requestHeaders.headers) {
let text = yield getLongString(value);
data.headers.push({ name: name, value: text });
}
- let { requestPostData } = yield requestData(selected.id, "requestPostData");
+ let { requestPostData } = yield requestData(id, "requestPostData");
// Fetch the request payload.
if (requestPostData) {
let postData = requestPostData.postData.text;
data.postDataText = yield getLongString(postData);
}
return data;
}
--- a/devtools/client/netmonitor/test/browser_net_filter-01.js
+++ b/devtools/client/netmonitor/test/browser_net_filter-01.js
@@ -312,18 +312,25 @@ add_task(function* () {
yield waitUntil(() => requestsListStatus.title);
}
isnot(getSelectedRequest(store.getState()), undefined,
"There should still be a selected item after filtering.");
is(getSelectedIndex(store.getState()), 0,
"The first item should be still selected after filtering.");
- const items = getSortedRequests(store.getState());
- const visibleItems = getDisplayedRequests(store.getState());
+ let items = getSortedRequests(store.getState());
+ let visibleItems;
+
+ // Filter results will be updated asynchronously, so we should wait until
+ // displayed requests reach final state.
+ yield waitUntil(() => {
+ visibleItems = getDisplayedRequests(store.getState());
+ return visibleItems.size === visibility.filter(e => e).length;
+ });
is(items.size, visibility.length,
"There should be a specific amount of items in the requests menu.");
is(visibleItems.size, visibility.filter(e => e).length,
"There should be a specific amount of visible items in the requests menu.");
for (let i = 0; i < visibility.length; i++) {
let itemId = items.get(i).id;
--- a/devtools/client/netmonitor/test/browser_net_filter-flags.js
+++ b/devtools/client/netmonitor/test/browser_net_filter-flags.js
@@ -140,18 +140,30 @@ add_task(function* () {
let Actions = windowRequire("devtools/client/netmonitor/src/actions/index");
let {
getDisplayedRequests,
getSortedRequests,
} = windowRequire("devtools/client/netmonitor/src/selectors/index");
store.dispatch(Actions.batchEnable(false));
+ function type(string) {
+ for (let ch of string) {
+ EventUtils.synthesizeKey(ch, {}, monitor.panelWin);
+ }
+ }
+
+ // Filtering network request will start fetching data lazily
+ // (fetching requestHeaders & responseHeaders for filtering WS & XHR)
+ // Lazy fetching will be executed when user focuses on filter box.
function setFreetextFilter(value) {
- store.dispatch(Actions.setRequestFilterText(value));
+ let filterBox = document.querySelector(".devtools-filterinput");
+ filterBox.focus();
+ filterBox.value = "";
+ type(value);
}
info("Starting test... ");
let waitNetwork = waitForNetworkEvents(monitor, REQUESTS.length);
loadCommonFrameScript();
yield performRequestsInContent(REQUESTS);
yield waitNetwork;
@@ -345,28 +357,44 @@ add_task(function* () {
let requestItems = document.querySelectorAll(".request-list-item");
for (let requestItem of requestItems) {
requestItem.scrollIntoView();
let requestsListStatus = requestItem.querySelector(".requests-list-status");
EventUtils.sendMouseEvent({ type: "mouseover" }, requestsListStatus);
yield waitUntil(() => requestsListStatus.title);
}
- const items = getSortedRequests(store.getState());
- const visibleItems = getDisplayedRequests(store.getState());
+ let items = getSortedRequests(store.getState());
+ let visibleItems = getDisplayedRequests(store.getState());
+
+ // Filter results will be updated asynchronously, so we should wait until
+ // displayed requests reach final state.
+ yield waitUntil(() => {
+ visibleItems = getDisplayedRequests(store.getState());
+ return visibleItems.size === visibility.filter(e => e).length;
+ });
is(items.size, visibility.length,
"There should be a specific amount of items in the requests menu.");
is(visibleItems.size, visibility.filter(e => e).length,
"There should be a specific amount of visible items in the requests menu.");
for (let i = 0; i < visibility.length; i++) {
let itemId = items.get(i).id;
let shouldBeVisible = !!visibility[i];
let isThere = visibleItems.some(r => r.id == itemId);
+
+ // Filter results will be updated asynchronously, so we should wait until
+ // displayed requests reach final state.
+ yield waitUntil(() => {
+ visibleItems = getDisplayedRequests(store.getState());
+ isThere = visibleItems.some(r => r.id == itemId);
+ return isThere === shouldBeVisible;
+ });
+
is(isThere, shouldBeVisible,
`The item at index ${i} has visibility=${shouldBeVisible}`);
if (shouldBeVisible) {
let { method, url, data } = EXPECTED_REQUESTS[i];
verifyRequestItemTarget(
document,
getDisplayedRequests(store.getState()),
--- a/devtools/client/netmonitor/test/browser_net_headers_sorted.js
+++ b/devtools/client/netmonitor/test/browser_net_headers_sorted.js
@@ -7,29 +7,36 @@
* Tests if Request-Headers and Response-Headers are sorted in Headers tab.
*/
add_task(function* () {
let { tab, monitor } = yield initNetMonitor(SIMPLE_SJS);
info("Starting test... ");
let { document, store, windowRequire } = monitor.panelWin;
let Actions = windowRequire("devtools/client/netmonitor/src/actions/index");
+ let {
+ getSortedRequests,
+ } = windowRequire("devtools/client/netmonitor/src/selectors/index");
store.dispatch(Actions.batchEnable(false));
+ let wait = waitForNetworkEvents(monitor, 1);
tab.linkedBrowser.reload();
-
- let wait = waitForNetworkEvents(monitor, 1);
yield wait;
wait = waitForDOM(document, ".headers-overview");
EventUtils.sendMouseEvent({ type: "mousedown" },
document.querySelectorAll(".request-list-item")[0]);
yield wait;
+ yield waitUntil(() => {
+ let request = getSortedRequests(store.getState()).get(0);
+ return request.requestHeaders && request.responseHeaders;
+ });
+
info("Check if Request-Headers and Response-Headers are sorted");
let expectedResponseHeaders = ["cache-control", "connection", "content-length",
"content-type", "date", "expires", "foo-bar",
"pragma", "server", "set-cookie"];
let expectedRequestHeaders = ["Accept", "Accept-Encoding", "Accept-Language",
"Cache-Control", "Connection", "Cookie", "Host",
"Pragma", "Upgrade-Insecure-Requests", "User-Agent"];
--- a/devtools/client/netmonitor/test/browser_net_persistent_logs.js
+++ b/devtools/client/netmonitor/test/browser_net_persistent_logs.js
@@ -7,36 +7,46 @@
* Tests if the network monitor leaks on initialization and sudden destruction.
* You can also use this initialization format as a template for other tests.
*/
add_task(function* () {
let { tab, monitor } = yield initNetMonitor(SINGLE_GET_URL);
info("Starting test... ");
- let { document } = monitor.panelWin;
+ let { document, store, windowRequire } = monitor.panelWin;
+ let Actions = windowRequire("devtools/client/netmonitor/src/actions/index");
+
+ store.dispatch(Actions.batchEnable(false));
Services.prefs.setBoolPref("devtools.netmonitor.persistlog", false);
yield reloadAndWait();
+ // Using waitUntil in the test is necessary to ensure all requests are added correctly.
+ // Because reloadAndWait call may catch early uncaught requests from initNetMonitor, so
+ // the actual number of requests after reloadAndWait could be wrong since all requests
+ // haven't finished.
+ yield waitUntil(() => document.querySelectorAll(".request-list-item").length === 2);
is(document.querySelectorAll(".request-list-item").length, 2,
"The request list should have two items at this point.");
yield reloadAndWait();
+ yield waitUntil(() => document.querySelectorAll(".request-list-item").length === 2);
// Since the reload clears the log, we still expect two requests in the log
is(document.querySelectorAll(".request-list-item").length, 2,
"The request list should still have two items at this point.");
// Now we toggle the persistence logs on
Services.prefs.setBoolPref("devtools.netmonitor.persistlog", true);
yield reloadAndWait();
+ yield waitUntil(() => document.querySelectorAll(".request-list-item").length === 4);
// Since we togged the persistence logs, we expect four items after the reload
is(document.querySelectorAll(".request-list-item").length, 4,
"The request list should now have four items at this point.");
Services.prefs.setBoolPref("devtools.netmonitor.persistlog", false);
return teardown(monitor);
/**
--- a/devtools/client/netmonitor/test/browser_net_raw_headers.js
+++ b/devtools/client/netmonitor/test/browser_net_raw_headers.js
@@ -20,17 +20,17 @@ add_task(function* () {
store.dispatch(Actions.batchEnable(false));
let wait = waitForNetworkEvents(monitor, 2);
yield ContentTask.spawn(tab.linkedBrowser, {}, function* () {
content.wrappedJSObject.performRequests();
});
yield wait;
- wait = waitForDOM(document, ".headers-overview");
+ wait = waitForDOM(document, "#headers-panel .tree-section", 2);
EventUtils.sendMouseEvent({ type: "mousedown" },
document.querySelectorAll(".request-list-item")[0]);
yield wait;
wait = waitForDOM(document, ".raw-headers-container textarea", 2);
EventUtils.sendMouseEvent({ type: "click" }, getRawHeadersButton());
yield wait;
--- a/devtools/client/netmonitor/test/browser_net_resend.js
+++ b/devtools/client/netmonitor/test/browser_net_resend.js
@@ -12,17 +12,16 @@ const ADD_HEADER = "Test-header: true";
const ADD_UA_HEADER = "User-Agent: Custom-Agent";
const ADD_POSTDATA = "&t3=t4";
add_task(function* () {
let { tab, monitor } = yield initNetMonitor(POST_DATA_URL);
info("Starting test... ");
let { document, store, windowRequire, connector } = monitor.panelWin;
- let { requestData } = connector;
let Actions = windowRequire("devtools/client/netmonitor/src/actions/index");
let {
getSelectedRequest,
getSortedRequests,
} = windowRequire("devtools/client/netmonitor/src/selectors/index");
store.dispatch(Actions.batchEnable(false));
@@ -51,17 +50,25 @@ add_task(function* () {
customItem = getSelectedRequest(store.getState());
testCustomItemChanged(customItem, origItem);
// send the new request
wait = waitForNetworkEvents(monitor, 1);
store.dispatch(Actions.sendCustomRequest(connector));
yield wait;
- let sentItem = getSelectedRequest(store.getState());
+ let sentItem;
+ // Testing sent request will require updated requestHeaders and requestPostData,
+ // we must wait for both properties get updated before starting test.
+ yield waitUntil(() => {
+ sentItem = getSelectedRequest(store.getState());
+ origItem = getSortedRequests(store.getState()).get(0);
+ return sentItem.requestHeaders && sentItem.requestPostData &&
+ origItem.requestHeaders && origItem.requestPostData;
+ });
yield testSentRequest(sentItem, origItem);
// Ensure the UI shows the new request, selected, and that the detail panel was closed.
is(getSortedRequests(store.getState()).length, 3, "There are 3 requests shown");
is(document.querySelector(".request-list-item.selected").getAttribute("data-id"),
sentItem.id, "The sent request is selected");
is(document.querySelector(".network-details-panel"), null,
@@ -159,23 +166,18 @@ add_task(function* () {
let { headers } = data.requestHeaders;
let hasHeader = headers.some(h => `${h.name}: ${h.value}` == ADD_HEADER);
ok(hasHeader, "new header added to sent request");
let hasUAHeader = headers.some(h => `${h.name}: ${h.value}` == ADD_UA_HEADER);
ok(hasUAHeader, "User-Agent header added to sent request");
- let { requestPostData: clonedRequestPostData } = yield requestData(data.id,
- "requestPostData");
- let { requestPostData: origRequestPostData } = yield requestData(origData.id,
- "requestPostData");
-
- is(clonedRequestPostData.postData.text,
- origRequestPostData.postData.text + ADD_POSTDATA,
+ is(data.requestPostData.postData.text,
+ origData.requestPostData.postData.text + ADD_POSTDATA,
"post data added to sent request");
}
function type(string) {
for (let ch of string) {
EventUtils.synthesizeKey(ch, {}, monitor.panelWin);
}
}
--- a/devtools/client/netmonitor/test/browser_net_resend_cors.js
+++ b/devtools/client/netmonitor/test/browser_net_resend_cors.js
@@ -10,16 +10,17 @@
add_task(function* () {
let { tab, monitor } = yield initNetMonitor(CORS_URL);
info("Starting test... ");
let { store, windowRequire, connector } = monitor.panelWin;
let Actions = windowRequire("devtools/client/netmonitor/src/actions/index");
let {
+ getRequestById,
getSortedRequests,
} = windowRequire("devtools/client/netmonitor/src/selectors/index");
store.dispatch(Actions.batchEnable(false));
let requestUrl = "http://test1.example.com" + CORS_SJS_PATH;
info("Waiting for OPTIONS, then POST");
@@ -36,45 +37,68 @@ add_task(function* () {
ITEMS.forEach((item, i) => {
is(item.method, METHODS[i], `The ${item.method} request has the right method`);
is(item.url, requestUrl, `The ${item.method} request has the right URL`);
});
// Resend both requests without modification. Wait for resent OPTIONS, then POST.
// POST is supposed to have no preflight OPTIONS request this time (CORS is disabled)
let onRequests = waitForNetworkEvents(monitor, 1);
- ITEMS.forEach((item) => {
+ for (let item of ITEMS) {
info(`Selecting the ${item.method} request`);
store.dispatch(Actions.selectRequest(item.id));
+ // Wait for requestHeaders and responseHeaders are required when fetching data
+ // from back-end.
+ yield waitUntil(() => {
+ item = getRequestById(store.getState(), item.id);
+ return item.requestHeaders && item.responseHeaders;
+ });
+
+ let { size } = getSortedRequests(store.getState());
+
info("Cloning the selected request into a custom clone");
store.dispatch(Actions.cloneSelectedRequest());
info("Sending the cloned request (without change)");
store.dispatch(Actions.sendCustomRequest(connector));
- });
+
+ yield waitUntil(() => getSortedRequests(store.getState()).size === size + 1);
+ }
info("Waiting for both resent requests");
yield onRequests;
// Check the resent requests
for (let i = 0; i < ITEMS.length; i++) {
let item = ITEMS[i];
is(item.method, METHODS[i], `The ${item.method} request has the right method`);
is(item.url, requestUrl, `The ${item.method} request has the right URL`);
is(item.status, 200, `The ${item.method} response has the right status`);
if (item.method === "POST") {
- // Force fetching lazy load data
- let responseContent = yield connector.requestData(item.id, "responseContent");
- let { requestPostData } = yield connector.requestData(item.id, "requestPostData");
+ is(item.method, "POST", `The ${item.method} request has the right method`);
- is(requestPostData.postData.text, "post-data",
+ // Trigger responseContent update requires to wait until
+ // responseContentAvailable set true
+ yield waitUntil(() => {
+ item = getRequestById(store.getState(), item.id);
+ return item.responseContentAvailable;
+ });
+ yield connector.requestData(item.id, "responseContent");
+
+ // Wait for both requestPostData & responseContent payloads arrived.
+ yield waitUntil(() => {
+ item = getRequestById(store.getState(), item.id);
+ return item.responseContent && item.requestPostData;
+ });
+
+ is(item.requestPostData.postData.text, "post-data",
"The POST request has the right POST data");
// eslint-disable-next-line mozilla/no-cpows-in-tests
- is(responseContent.content.text, "Access-Control-Allow-Origin: *",
+ is(item.responseContent.content.text, "Access-Control-Allow-Origin: *",
"The POST response has the right content");
}
}
info("Finishing the test");
return teardown(monitor);
});
--- a/devtools/client/netmonitor/test/browser_net_resend_headers.js
+++ b/devtools/client/netmonitor/test/browser_net_resend_headers.js
@@ -8,17 +8,17 @@
*/
add_task(function* () {
let { monitor } = yield initNetMonitor(SIMPLE_SJS);
info("Starting test... ");
let { store, windowRequire, connector } = monitor.panelWin;
let Actions = windowRequire("devtools/client/netmonitor/src/actions/index");
- let { sendHTTPRequest } = connector;
+ let { requestData, sendHTTPRequest } = connector;
let {
getSortedRequests,
} = windowRequire("devtools/client/netmonitor/src/selectors/index");
store.dispatch(Actions.batchEnable(false));
let requestUrl = SIMPLE_SJS;
let requestHeaders = [
@@ -35,16 +35,29 @@ add_task(function* () {
url: requestUrl,
method: "POST",
headers: requestHeaders,
body: "Hello"
});
yield wait;
let item = getSortedRequests(store.getState()).get(0);
+
+ ok(item.requestHeadersAvailable, "headers are available for lazily fetching");
+
+ if (item.requestHeadersAvailable && !item.requestHeaders) {
+ requestData(item.id, "requestHeaders");
+ }
+
+ // Wait until requestHeaders packet gets updated.
+ yield waitUntil(() => {
+ item = getSortedRequests(store.getState()).get(0);
+ return item.requestHeaders;
+ });
+
is(item.method, "POST", "The request has the right method");
is(item.url, requestUrl, "The request has the right URL");
for (let { name, value } of item.requestHeaders.headers) {
info(`Request header: ${name}: ${value}`);
}
function hasRequestHeader(name, value) {
--- a/devtools/client/netmonitor/test/browser_net_security-error.js
+++ b/devtools/client/netmonitor/test/browser_net_security-error.js
@@ -6,23 +6,22 @@
/**
* Test that Security details tab shows an error message with broken connections.
*/
add_task(function* () {
let { tab, monitor } = yield initNetMonitor(CUSTOM_GET_URL);
let { document, store, windowRequire } = monitor.panelWin;
let Actions = windowRequire("devtools/client/netmonitor/src/actions/index");
- let { EVENTS } = windowRequire("devtools/client/netmonitor/src/constants");
store.dispatch(Actions.batchEnable(false));
info("Requesting a resource that has a certificate problem.");
- let requestsDone = waitForSecurityBrokenNetworkEvent();
+ let requestsDone = waitForNetworkEvents(monitor, 1);
yield ContentTask.spawn(tab.linkedBrowser, {}, function* () {
content.wrappedJSObject.performRequests(1, "https://nocert.example.com");
});
yield requestsDone;
let securityInfoLoaded = waitForDOM(document, ".security-info-value");
EventUtils.sendMouseEvent({ type: "click" },
document.querySelector(".network-details-panel-toggle"));
@@ -31,30 +30,9 @@ add_task(function* () {
EventUtils.sendMouseEvent({ type: "click" },
document.querySelector("#security-tab"));
yield securityInfoLoaded;
let errormsg = document.querySelector(".security-info-value");
isnot(errormsg.textContent, "", "Error message is not empty.");
return teardown(monitor);
-
- /**
- * Returns a promise that's resolved once a request with security issues is
- * completed.
- */
- function waitForSecurityBrokenNetworkEvent() {
- let awaitedEvents = [
- "UPDATING_REQUEST_HEADERS",
- "RECEIVED_REQUEST_HEADERS",
- "UPDATING_REQUEST_COOKIES",
- "RECEIVED_REQUEST_COOKIES",
- "UPDATING_EVENT_TIMINGS",
- "RECEIVED_EVENT_TIMINGS",
- ];
-
- let promises = awaitedEvents.map((event) => {
- return monitor.panelWin.once(EVENTS[event]);
- });
-
- return Promise.all(promises);
- }
});
--- a/devtools/client/netmonitor/test/browser_net_security-state.js
+++ b/devtools/client/netmonitor/test/browser_net_security-state.js
@@ -51,20 +51,17 @@ add_task(function* () {
*/
function* performRequests() {
function executeRequests(count, url) {
return ContentTask.spawn(tab.linkedBrowser, {count, url}, function* (args) {
content.wrappedJSObject.performRequests(args.count, args.url);
});
}
- // waitForNetworkEvents does not work for requests with security errors as
- // those only emit 9/13 events of a successful request.
- let done = waitForSecurityBrokenNetworkEvent();
-
+ let done = waitForNetworkEvents(monitor, 1);
info("Requesting a resource that has a certificate problem.");
yield executeRequests(1, "https://nocert.example.com");
// Wait for the request to complete before firing another request. Otherwise
// the request with security issues interfere with waitForNetworkEvents.
info("Waiting for request to complete.");
yield done;
@@ -75,40 +72,19 @@ add_task(function* () {
yield executeRequests(1, "http://test1.example.com" + CORS_SJS_PATH);
yield done;
done = waitForNetworkEvents(monitor, 1);
info("Requesting a resource over HTTPS.");
yield executeRequests(1, "https://example.com" + CORS_SJS_PATH);
yield done;
- done = waitForSecurityBrokenNetworkEvent();
+ done = waitForNetworkEvents(monitor, 1);
info("Requesting a resource over HTTP to localhost.");
yield executeRequests(1, "http://localhost" + CORS_SJS_PATH);
yield done;
const expectedCount = Object.keys(EXPECTED_SECURITY_STATES).length;
is(store.getState().requests.requests.size,
expectedCount,
expectedCount + " events logged.");
}
-
- /**
- * Returns a promise that's resolved once a request with security issues is
- * completed.
- */
- function waitForSecurityBrokenNetworkEvent() {
- let awaitedEvents = [
- "UPDATING_REQUEST_HEADERS",
- "RECEIVED_REQUEST_HEADERS",
- "UPDATING_REQUEST_COOKIES",
- "RECEIVED_REQUEST_COOKIES",
- "UPDATING_EVENT_TIMINGS",
- "RECEIVED_EVENT_TIMINGS",
- ];
-
- let promises = awaitedEvents.map((event) => {
- return monitor.panelWin.once(EVENTS[event]);
- });
-
- return Promise.all(promises);
- }
});
--- a/devtools/client/netmonitor/test/browser_net_security-tab-visibility.js
+++ b/devtools/client/netmonitor/test/browser_net_security-tab-visibility.js
@@ -96,20 +96,16 @@ add_task(function* () {
return teardown(monitor);
/**
* Returns a promise that's resolved once a request with security issues is
* completed.
*/
function waitForSecurityBrokenNetworkEvent() {
let awaitedEvents = [
- "UPDATING_REQUEST_HEADERS",
- "RECEIVED_REQUEST_HEADERS",
- "UPDATING_REQUEST_COOKIES",
- "RECEIVED_REQUEST_COOKIES",
"UPDATING_EVENT_TIMINGS",
"RECEIVED_EVENT_TIMINGS",
];
let promises = awaitedEvents.map((event) => {
return monitor.panelWin.once(EVENTS[event]);
});
--- a/devtools/client/netmonitor/test/browser_net_simple-request-data.js
+++ b/devtools/client/netmonitor/test/browser_net_simple-request-data.js
@@ -22,17 +22,17 @@ function test() {
// number of response headers will vary depending on the platform.
Services.prefs.setBoolPref("network.tcp.tcp_fastopen_enable", false);
let { L10N } = require("devtools/client/netmonitor/src/utils/l10n");
initNetMonitor(SIMPLE_SJS).then(async ({ tab, monitor }) => {
info("Starting test... ");
- let { document, store, windowRequire } = monitor.panelWin;
+ let { document, store, windowRequire, connector } = monitor.panelWin;
let Actions = windowRequire("devtools/client/netmonitor/src/actions/index");
let { EVENTS } = windowRequire("devtools/client/netmonitor/src/constants");
let {
getDisplayedRequests,
getSelectedRequest,
getSortedRequests,
} = windowRequire("devtools/client/netmonitor/src/selectors/index");
@@ -342,15 +342,26 @@ function test() {
"GET",
SIMPLE_SJS,
{
time: true
}
);
});
+ let wait = waitForNetworkEvents(monitor, 1);
tab.linkedBrowser.reload();
+ await wait;
+
+ let requestItem = getSortedRequests(store.getState()).get(0);
+
+ if (!requestItem.requestHeaders) {
+ connector.requestData(requestItem.id, "requestHeaders");
+ }
+ if (!requestItem.responseHeaders) {
+ connector.requestData(requestItem.id, "responseHeaders");
+ }
await Promise.all(promiseList);
await teardown(monitor);
finish();
});
}
--- a/devtools/client/netmonitor/test/browser_net_status-codes.js
+++ b/devtools/client/netmonitor/test/browser_net_status-codes.js
@@ -167,16 +167,19 @@ add_task(function* () {
/**
* A function that tests "Headers" panel contains correct information.
*/
function* testHeaders(data, index) {
EventUtils.sendMouseEvent({ type: "mousedown" },
document.querySelectorAll(".request-list-item")[index]);
+ yield waitUntil(() => document.querySelector(
+ "#headers-panel .tabpanel-summary-value.textbox-input"));
+
let panel = document.querySelector("#headers-panel");
let summaryValues = panel.querySelectorAll(".tabpanel-summary-value.textbox-input");
let { method, correctUri, details: { status, statusText } } = data;
is(summaryValues[0].value, correctUri,
"The url summary value is incorrect.");
is(summaryValues[1].value, method, "The method summary value is incorrect.");
is(panel.querySelector(".requests-list-status-icon").dataset.code, status,
--- a/devtools/client/netmonitor/test/browser_net_timing-division.js
+++ b/devtools/client/netmonitor/test/browser_net_timing-division.js
@@ -8,20 +8,16 @@
*/
add_task(function* () {
let { tab, monitor } = yield initNetMonitor(CUSTOM_GET_URL);
info("Starting test... ");
let { document, store, windowRequire } = monitor.panelWin;
let Actions = windowRequire("devtools/client/netmonitor/src/actions/index");
- let {
- getSortedRequests,
- } = windowRequire("devtools/client/netmonitor/src/selectors/index");
-
store.dispatch(Actions.batchEnable(false));
let wait = waitForNetworkEvents(monitor, 2);
// Timeout needed for having enough divisions on the time scale.
yield ContentTask.spawn(tab.linkedBrowser, {}, function* () {
content.wrappedJSObject.performRequests(2, null, 3000);
});
yield wait;
@@ -39,23 +35,15 @@ add_task(function* () {
milDivs.forEach(div => info(`Millisecond division: ${div.textContent}`));
secDivs.forEach(div => info(`Second division: ${div.textContent}`));
minDivs.forEach(div => info(`Minute division: ${div.textContent}`));
is(store.getState().requests.requests.size, 2,
"There should be only two requests made.");
- let firstRequest = getSortedRequests(store.getState()).get(0);
- let lastRequest = getSortedRequests(store.getState()).get(1);
-
- info("First request happened at: " +
- firstRequest.responseHeaders.headers.find(e => e.name == "date").value);
- info("Last request happened at: " +
- lastRequest.responseHeaders.headers.find(e => e.name == "date").value);
-
ok(secDivs.length,
"There should be at least one division on the seconds time scale.");
ok(secDivs[0].textContent.match(/\d+\.\d{2}\s\w+/),
"The division on the seconds time scale looks legit.");
return teardown(monitor);
});
--- a/devtools/client/netmonitor/test/browser_net_waterfall-click.js
+++ b/devtools/client/netmonitor/test/browser_net_waterfall-click.js
@@ -6,31 +6,27 @@
/**
* Test that clicking on the waterfall opens the timing sidebar panel.
*/
add_task(function* () {
let { tab, monitor } = yield initNetMonitor(CONTENT_TYPE_WITHOUT_CACHE_URL);
let { document } = monitor.panelWin;
- yield performRequestsAndWait();
-
- let wait = waitForDOM(document, "#timings-panel");
- let timing = document.querySelectorAll(".requests-list-timings")[0];
+ let onAllEvents = waitForNetworkEvents(monitor, CONTENT_TYPE_WITHOUT_CACHE_REQUESTS);
+ yield ContentTask.spawn(tab.linkedBrowser, {}, function* () {
+ content.wrappedJSObject.performRequests();
+ });
+ yield onAllEvents;
info("Clicking waterfall and waiting for panel update.");
- EventUtils.synthesizeMouseAtCenter(timing, {}, monitor.panelWin);
+ let wait = waitForDOM(document, "#timings-panel");
+
+ EventUtils.sendMouseEvent({ type: "mousedown" },
+ document.querySelectorAll(".requests-list-timings")[0]);
yield wait;
ok(document.querySelector("#timings-tab[aria-selected=true]"),
"Timings tab is selected.");
return teardown(monitor);
-
- function* performRequestsAndWait() {
- let onAllEvents = waitForNetworkEvents(monitor, CONTENT_TYPE_WITHOUT_CACHE_REQUESTS);
- yield ContentTask.spawn(tab.linkedBrowser, {}, function* () {
- content.wrappedJSObject.performRequests();
- });
- yield onAllEvents;
- }
});
--- a/devtools/client/netmonitor/test/head.js
+++ b/devtools/client/netmonitor/test/head.js
@@ -1,40 +1,36 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/* import-globals-from ../../framework/test/shared-head.js */
-/* import-globals-from shared-head.js */
/* exported Toolbox, restartNetMonitor, teardown, waitForExplicitFinish,
verifyRequestItemTarget, waitFor, testFilterButtons, loadCommonFrameScript,
performRequestsInContent, waitForNetworkEvents, selectIndexAndWaitForSourceEditor */
"use strict";
// shared-head.js handles imports, constants, and utility functions
Services.scriptloader.loadSubScript(
"chrome://mochitests/content/browser/devtools/client/framework/test/shared-head.js",
this);
-Services.scriptloader.loadSubScript(
- "chrome://mochitests/content/browser/devtools/client/netmonitor/test/shared-head.js",
- this);
-
const {
getFormattedIPAndPort,
getFormattedTime,
} = require("devtools/client/netmonitor/src/utils/format-utils");
const {
decodeUnicodeUrl,
getFormattedProtocol,
getUrlBaseName,
getUrlHost,
getUrlQuery,
getUrlScheme,
} = require("devtools/client/netmonitor/src/utils/request-utils");
+const { EVENTS } = require("devtools/client/netmonitor/src/constants");
/* eslint-disable no-unused-vars, max-len */
const EXAMPLE_URL = "http://example.com/browser/devtools/client/netmonitor/test/";
const HTTPS_EXAMPLE_URL = "https://example.com/browser/devtools/client/netmonitor/test/";
const API_CALLS_URL = EXAMPLE_URL + "html_api-calls-test-page.html";
const SIMPLE_URL = EXAMPLE_URL + "html_simple-test-page.html";
const NAVIGATE_URL = EXAMPLE_URL + "html_navigate-test-page.html";
@@ -220,33 +216,45 @@ function waitForAllRequestsFinished(moni
window.on(EVENTS.PAYLOAD_READY, onTimings);
});
}
let finishedQueue = {};
let updatingTypes = [
"NetMonitor:NetworkEventUpdating:RequestCookies",
"NetMonitor:NetworkEventUpdating:ResponseCookies",
+ "NetMonitor:NetworkEventUpdating:RequestHeaders",
+ "NetMonitor:NetworkEventUpdating:ResponseHeaders",
+ "NetMonitor:NetworkEventUpdating:RequestPostData",
+ "NetMonitor:NetworkEventUpdating:ResponseContent",
+ "NetMonitor:NetworkEventUpdating:SecurityInfo",
+ "NetMonitor:NetworkEventUpdating:EventTimings",
];
let updatedTypes = [
"NetMonitor:NetworkEventUpdated:RequestCookies",
"NetMonitor:NetworkEventUpdated:ResponseCookies",
+ "NetMonitor:NetworkEventUpdated:RequestHeaders",
+ "NetMonitor:NetworkEventUpdated:ResponseHeaders",
+ "NetMonitor:NetworkEventUpdated:RequestPostData",
+ "NetMonitor:NetworkEventUpdated:ResponseContent",
+ "NetMonitor:NetworkEventUpdated:SecurityInfo",
+ "NetMonitor:NetworkEventUpdated:EventTimings",
];
// Start collecting all networkEventUpdate event when panel is opened.
// removeTab() should be called once all corresponded RECEIVED_* events finished.
function startNetworkEventUpdateObserver(panelWin) {
updatingTypes.forEach((type) => panelWin.on(type, (event, actor) => {
- let key = actor + "-" + event.replace("NetMonitor:NetworkEventUpdating:", "");
+ let key = actor + "-" + updatedTypes[updatingTypes.indexOf(event)];
finishedQueue[key] = finishedQueue[key] ? finishedQueue[key] + 1 : 1;
}));
updatedTypes.forEach((type) => panelWin.on(type, (event, actor) => {
- let key = actor + "-" + event.replace("NetMonitor:NetworkEventUpdated:", "");
- finishedQueue[key]--;
+ let key = actor + "-" + event;
+ finishedQueue[key] = finishedQueue[key] ? finishedQueue[key] - 1 : -1;
}));
}
function* waitForAllNetworkUpdateEvents() {
function checkNetworkEventUpdateState() {
for (let key in finishedQueue) {
if (finishedQueue[key] > 0) {
return false;
@@ -324,113 +332,74 @@ function restartNetMonitor(monitor, newU
}
function teardown(monitor) {
info("Destroying the specified network monitor.");
return Task.spawn(function* () {
let tab = monitor.toolbox.target.tab;
- // Ensure that there is no pending RDP requests related to payload request
- // done from FirefoxDataProvider.
- info("Wait for completion of all pending RDP requests...");
- yield waitForExistingRequests(monitor);
yield waitForAllNetworkUpdateEvents();
info("All pending requests finished.");
let onDestroyed = monitor.once("destroyed");
yield removeTab(tab);
yield onDestroyed;
});
}
function waitForNetworkEvents(monitor, getRequests) {
return new Promise((resolve) => {
let panel = monitor.panelWin;
let { getNetworkRequest } = panel.connector;
- let progress = {};
- let genericEvents = 0;
+ let networkEvent = 0;
let payloadReady = 0;
- let awaitedEventsToListeners = [
- ["UPDATING_REQUEST_HEADERS", onGenericEvent],
- ["RECEIVED_REQUEST_HEADERS", onGenericEvent],
- ["UPDATING_RESPONSE_HEADERS", onGenericEvent],
- ["RECEIVED_RESPONSE_HEADERS", onGenericEvent],
- ["UPDATING_EVENT_TIMINGS", onGenericEvent],
- ["RECEIVED_EVENT_TIMINGS", onGenericEvent],
- ["PAYLOAD_READY", onPayloadReady]
- ];
- let expectedGenericEvents = awaitedEventsToListeners
- .filter(([, listener]) => listener == onGenericEvent).length;
- function initProgressForURL(url) {
- if (progress[url]) {
- return;
- }
- progress[url] = {};
- awaitedEventsToListeners.forEach(function ([e]) {
- progress[url][e] = 0;
- });
- }
-
- function updateProgressForURL(url, event) {
- initProgressForURL(url);
- progress[url][Object.keys(EVENTS).find(e => EVENTS[e] == event)] = 1;
- }
-
- function onGenericEvent(event, actor) {
+ function onNetworkEvent(event, actor) {
let networkInfo = getNetworkRequest(actor);
if (!networkInfo) {
// Must have been related to reloading document to disable cache.
// Ignore the event.
return;
}
- genericEvents++;
+ networkEvent++;
maybeResolve(event, actor, networkInfo);
}
function onPayloadReady(event, actor) {
let networkInfo = getNetworkRequest(actor);
if (!networkInfo) {
// Must have been related to reloading document to disable cache.
// Ignore the event.
return;
}
-
payloadReady++;
maybeResolve(event, actor, networkInfo);
}
function maybeResolve(event, actor, networkInfo) {
info("> Network event progress: " +
- "Payload: " + payloadReady + "/" + getRequests + ", " +
- "Generic: " + genericEvents + "/" + (getRequests * expectedGenericEvents) + ", " +
+ "NetworkEvent: " + networkEvent + "/" + getRequests + ", " +
+ "PayloadReady: " + payloadReady + "/" + getRequests + ", " +
"got " + event + " for " + actor);
- let url = networkInfo.request.url;
- updateProgressForURL(url, event);
-
- // Uncomment this to get a detailed progress logging (when debugging a test)
- // info("> Current state: " + JSON.stringify(progress, null, 2));
-
- // There are `expectedGenericEvents` updates which need to be fired for a request
- // to be considered finished. The "requestPostData" packet isn't fired for non-POST
- // requests.
- if (payloadReady >= getRequests &&
- genericEvents >= getRequests * expectedGenericEvents) {
- awaitedEventsToListeners.forEach(([e, l]) => panel.off(EVENTS[e], l));
+ // Wait until networkEvent & payloadReady finish for each request.
+ if (networkEvent >= getRequests && payloadReady >= getRequests) {
+ panel.off(EVENTS.NETWORK_EVENT, onNetworkEvent);
+ panel.off(EVENTS.PAYLOAD_READY, onPayloadReady);
executeSoon(resolve);
}
}
- awaitedEventsToListeners.forEach(([e, l]) => panel.on(EVENTS[e], l));
+ panel.on(EVENTS.NETWORK_EVENT, onNetworkEvent);
+ panel.on(EVENTS.PAYLOAD_READY, onPayloadReady);
});
}
-function verifyRequestItemTarget(document, requestList, requestItem, method,
+function* verifyRequestItemTarget(document, requestList, requestItem, method,
url, data = {}) {
info("> Verifying: " + method + " " + url + " " + data.toSource());
let visibleIndex = requestList.indexOf(requestItem);
info("Visible index of item: " + visibleIndex);
let { fuzzyUrl, status, statusText, cause, type, fullMimeType,
deleted file mode 100644
--- a/devtools/client/netmonitor/test/shared-head.js
+++ /dev/null
@@ -1,40 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- http://creativecommons.org/publicdomain/zero/1.0/ */
-
-/* exported EVENTS, waitForExistingRequests */
-
-"use strict";
-
-const { EVENTS } = require("devtools/client/netmonitor/src/constants");
-
-async function waitForExistingRequests(monitor) {
- let { store } = monitor.panelWin;
- function getRequests() {
- return store.getState().requests.requests;
- }
- function areAllRequestsFullyLoaded() {
- let requests = getRequests().valueSeq();
- for (let request of requests) {
- // Ignore cloned request as we don't lazily fetch data for them
- // and have arbitrary number of field set.
- if (request.id.includes("-clone")) {
- continue;
- }
- // Do same check than FirefoxDataProvider.isRequestPayloadReady,
- // in order to ensure there is no more pending payload requests to be done.
- if (!request.requestHeaders || !request.eventTimings ||
- (!request.responseHeaders && request.securityState !== "broken" &&
- (!request.responseContentAvailable || request.status))) {
- return false;
- }
- }
- return true;
- }
- // If there is no request, we are good to go.
- if (getRequests().size == 0) {
- return;
- }
- while (!areAllRequestsFullyLoaded()) {
- await monitor.panelWin.once(EVENTS.PAYLOAD_READY);
- }
-}
--- a/devtools/client/styleeditor/test/browser.ini
+++ b/devtools/client/styleeditor/test/browser.ini
@@ -56,17 +56,16 @@ support-files =
doc_xulpage.xul
sync.html
utf-16.css
!/devtools/client/commandline/test/helpers.js
!/devtools/client/framework/test/shared-head.js
!/devtools/client/inspector/shared/test/head.js
!/devtools/client/inspector/test/head.js
!/devtools/client/inspector/test/shared-head.js
- !/devtools/client/netmonitor/test/shared-head.js
!/devtools/client/responsive.html/test/browser/devices.json
!/devtools/client/shared/test/test-actor-registry.js
!/devtools/client/shared/test/test-actor.js
[browser_styleeditor_add_stylesheet.js]
[browser_styleeditor_autocomplete.js]
[browser_styleeditor_autocomplete-disabled.js]
[browser_styleeditor_bom.js]
--- a/devtools/client/styleeditor/test/browser_styleeditor_fetch-from-cache.js
+++ b/devtools/client/styleeditor/test/browser_styleeditor_fetch-from-cache.js
@@ -1,21 +1,16 @@
/* vim: set ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
-/* import-globals-from ../../netmonitor/test/shared-head.js */
-
// A test to ensure Style Editor doesn't bybass cache when loading style sheet
// contents (bug 978688).
-Services.scriptloader.loadSubScript(
- "chrome://mochitests/content/browser/devtools/client/netmonitor/test/shared-head.js", this);
-
const TEST_URL = TEST_BASE_HTTP + "doc_uncached.html";
add_task(function* () {
// Disable rcwn to make cache behavior deterministic.
yield pushPref("network.http.rcwn.enabled", false);
info("Opening netmonitor");
let tab = yield addTab("about:blank");
@@ -34,18 +29,16 @@ add_task(function* () {
yield navigateTo(TEST_URL);
info("Opening Style Editor");
let styleeditor = yield toolbox.selectTool("styleeditor");
info("Waiting for the source to be loaded.");
yield styleeditor.UI.editors[0].getSourceEditor();
- yield waitForExistingRequests(monitor);
-
info("Checking Netmonitor contents.");
let items = [];
for (let item of getSortedRequests(store.getState())) {
if (item.url.endsWith("doc_uncached.css")) {
items.push(item);
}
}
--- a/devtools/client/webconsole/new-console-output/test/mochitest/browser.ini
+++ b/devtools/client/webconsole/new-console-output/test/mochitest/browser.ini
@@ -160,17 +160,16 @@ support-files =
test-subresource-security-error.js
test-subresource-security-error.js^headers^
test-trackingprotection-securityerrors.html
test-webconsole-error-observer.html
testscript.js
!/devtools/client/netmonitor/test/sjs_cors-test-server.sjs
!/image/test/mochitest/blue.png
!/devtools/client/framework/test/shared-head.js
- !/devtools/client/netmonitor/test/shared-head.js
[browser_console.js]
skip-if = true # Bug 1406060
[browser_console_addonsdk_loader_exception.js]
skip-if = true # Bug 1406060
[browser_console_clear_method.js]
skip-if = true # Bug 1406060
[browser_console_consolejsm_output.js]
skip-if = true # Bug 1406060
--- a/devtools/client/webconsole/new-console-output/test/mochitest/browser_netmonitor_shows_reqs_in_webconsole.js
+++ b/devtools/client/webconsole/new-console-output/test/mochitest/browser_netmonitor_shows_reqs_in_webconsole.js
@@ -59,11 +59,9 @@ async function testNetmonitor(toolbox) {
await waitUntil(() => store.getState().requests.requests.size > 0);
is(store.getState().requests.requests.size, 1,
"Network request appears in the network panel");
let item = getSortedRequests(store.getState()).get(0);
is(item.method, "GET", "The attached method is correct.");
is(item.url, TEST_PATH, "The attached url is correct.");
-
- await waitForExistingRequests(monitor);
}
--- a/devtools/client/webconsole/new-console-output/test/mochitest/browser_webconsole_network_attach.js
+++ b/devtools/client/webconsole/new-console-output/test/mochitest/browser_webconsole_network_attach.js
@@ -42,24 +42,39 @@ add_task(async function task() {
let consoleReady = ui.jsterm.hud.once("network-request-payload-ready");
// Expand network log
urlNode.click();
await consoleReady;
info("network-request-payload-ready received");
-
await testNetworkMessage(messageNode);
-
- await waitForExistingRequests(monitor);
+ await waitForLazyRequests(toolbox);
});
async function testNetworkMessage(messageNode) {
let headersTab = messageNode.querySelector("#headers-tab");
ok(headersTab, "Headers tab is available");
// Headers tab should be selected by default, so just check its content.
- let headersContent = messageNode.querySelector(
- "#headers-panel .headers-overview");
+ let headersContent;
+ await waitUntil(() => {
+ headersContent = messageNode.querySelector(
+ "#headers-panel .headers-overview");
+ return headersContent;
+ });
+
ok(headersContent, "Headers content is available");
}
+
+/**
+ * Wait until all lazily fetch requests in netmonitor get finsished.
+ * Otherwise test will be shutdown too early and cause failure.
+ */
+async function waitForLazyRequests(toolbox) {
+ let { ui } = toolbox.getCurrentPanel().hud;
+ let proxy = ui.jsterm.hud.proxy;
+ return waitUntil(() => {
+ return !proxy.networkDataProvider.lazyRequestData.size;
+ });
+}
--- a/devtools/client/webconsole/new-console-output/test/mochitest/browser_webconsole_network_messages_expand.js
+++ b/devtools/client/webconsole/new-console-output/test/mochitest/browser_webconsole_network_messages_expand.js
@@ -242,16 +242,20 @@ function testEmptyTimings(messageNode) {
}
async function testTimings(messageNode) {
let timingsTab = messageNode.querySelector("#timings-tab");
ok(timingsTab, "Timings tab is available");
// Select Timings tab and check the content.
timingsTab.click();
+ await waitUntil(() => {
+ return !!messageNode.querySelector(
+ "#timings-panel .timings-container .timings-label");
+ });
let timingsContent = messageNode.querySelector(
"#timings-panel .timings-container .timings-label");
ok(timingsContent, "Timings content is available");
ok(timingsContent.textContent, "Timings text is available");
}
// Stack Trace
@@ -294,15 +298,19 @@ async function waitForRequestUpdates(too
return new Promise(resolve => {
ui.jsterm.hud.on("network-message-updated", () => {
info("network-message-updated received");
resolve();
});
});
}
+/**
+ * Wait until all lazily fetch requests in netmonitor get finsished.
+ * Otherwise test will be shutdown too early and cause failure.
+ */
async function waitForLazyRequests(toolbox) {
let {ui} = toolbox.getCurrentPanel().hud;
let proxy = ui.jsterm.hud.proxy;
return waitUntil(() => {
return !proxy.networkDataProvider.lazyRequestData.size;
});
}
--- a/devtools/client/webconsole/new-console-output/test/mochitest/browser_webconsole_network_messages_openinnet.js
+++ b/devtools/client/webconsole/new-console-output/test/mochitest/browser_webconsole_network_messages_openinnet.js
@@ -70,12 +70,9 @@ async function testNetmonitorLink(toolbo
store.dispatch(actions.batchEnable(false));
await waitUntil(() => {
const selected = getSelectedRequest(store.getState());
return selected && selected.url === url;
});
ok(true, "The attached url is correct.");
-
- let monitor = toolbox.getCurrentPanel();
- await waitForExistingRequests(monitor);
}
--- a/devtools/client/webconsole/new-console-output/test/mochitest/head.js
+++ b/devtools/client/webconsole/new-console-output/test/mochitest/head.js
@@ -1,27 +1,23 @@
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
/* import-globals-from ../../../../framework/test/shared-head.js */
-/* import-globals-from ../../../../netmonitor/test/shared-head.js */
/* eslint no-unused-vars: [2, {"vars": "local"}] */
"use strict";
// shared-head.js handles imports, constants, and utility functions
// Load the shared-head file first.
Services.scriptloader.loadSubScript(
"chrome://mochitests/content/browser/devtools/client/framework/test/shared-head.js",
this);
-Services.scriptloader.loadSubScript(
- "chrome://mochitests/content/browser/devtools/client/netmonitor/test/shared-head.js", this);
-
var {HUDService} = require("devtools/client/webconsole/hudservice");
var WCUL10n = require("devtools/client/webconsole/webconsole-l10n");
const DOCS_GA_PARAMS = "?utm_source=mozilla" +
"&utm_medium=firefox-console-errors" +
"&utm_campaign=default";
Services.prefs.setBoolPref("devtools.webconsole.new-frontend-enabled", true);
registerCleanupFunction(function* () {
--- a/devtools/client/webconsole/test/browser_netmonitor_shows_reqs_in_webconsole.js
+++ b/devtools/client/webconsole/test/browser_netmonitor_shows_reqs_in_webconsole.js
@@ -1,18 +1,15 @@
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
-Services.scriptloader.loadSubScript(
- "chrome://mochitests/content/browser/devtools/client/netmonitor/test/shared-head.js", this);
-
const TEST_URI = "data:text/html;charset=utf8,Test that the netmonitor " +
"displays requests that have been recorded in the " +
"web console, even if the netmonitor hadn't opened yet.";
const TEST_FILE = "test-network-request.html";
const TEST_PATH = "http://example.com/browser/devtools/client/webconsole/" +
"test/" + TEST_FILE;
@@ -63,22 +60,22 @@ function loadDocument(browser) {
return deferred.promise;
}
function* testNetmonitor(toolbox) {
let monitor = toolbox.getCurrentPanel();
let { store, windowRequire } = monitor.panelWin;
let Actions = windowRequire("devtools/client/netmonitor/src/actions/index");
- let { getSortedRequests } = windowRequire("devtools/client/netmonitor/src/selectors/index");
+ let { getSortedRequests } =
+ windowRequire("devtools/client/netmonitor/src/selectors/index");
store.dispatch(Actions.batchEnable(false));
yield waitUntil(() => store.getState().requests.requests.size > 0);
- is(store.getState().requests.requests.size, 1, "Network request appears in the network panel");
+ is(store.getState().requests.requests.size, 1,
+ "Network request appears in the network panel");
let item = getSortedRequests(store.getState()).get(0);
is(item.method, "GET", "The attached method is correct.");
is(item.url, TEST_PATH, "The attached url is correct.");
-
- yield waitForExistingRequests(monitor);
}
--- a/devtools/client/webconsole/test/browser_webconsole_netlogging_panel.js
+++ b/devtools/client/webconsole/test/browser_webconsole_netlogging_panel.js
@@ -1,41 +1,35 @@
/* vim:set ts=2 sw=2 sts=2 et: */
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
-/* import-globals-from ../../netmonitor/test/shared-head.js */
-
// Tests that network log messages bring up the network panel.
"use strict";
const TEST_NETWORK_REQUEST_URI =
"http://example.com/browser/devtools/client/webconsole/test/" +
"test-network-request.html";
-Services.scriptloader.loadSubScript(
- "chrome://mochitests/content/browser/devtools/client/netmonitor/test/shared-head.js", this);
-
add_task(function* () {
let finishedRequest = waitForFinishedRequest(({ request }) => {
return request.url.endsWith("test-network-request.html");
});
const hud = yield loadPageAndGetHud(TEST_NETWORK_REQUEST_URI);
let request = yield finishedRequest;
yield hud.ui.openNetworkPanel(request.actor);
let toolbox = gDevTools.getToolbox(hud.target);
is(toolbox.currentToolId, "netmonitor", "Network panel was opened");
let monitor = toolbox.getCurrentPanel();
let { store, windowRequire } = monitor.panelWin;
- let { getSelectedRequest } = windowRequire("devtools/client/netmonitor/src/selectors/index");
+ let { getSelectedRequest } =
+ windowRequire("devtools/client/netmonitor/src/selectors/index");
let selected = getSelectedRequest(store.getState());
is(selected.method, request.request.method,
"The correct request is selected");
is(selected.url, request.request.url,
"The correct request is definitely selected");
-
- yield waitForExistingRequests(monitor);
});
--- a/devtools/client/webconsole/test/browser_webconsole_netlogging_reset_filter.js
+++ b/devtools/client/webconsole/test/browser_webconsole_netlogging_reset_filter.js
@@ -1,28 +1,23 @@
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
-/* import-globals-from ../../netmonitor/test/shared-head.js */
-
// Tests that network log messages bring up the network panel and select the
// right request even if it was previously filtered off.
"use strict";
const TEST_FILE_URI =
"http://example.com/browser/devtools/client/webconsole/test/" +
"test-network.html";
const TEST_URI = "data:text/html;charset=utf8,<p>test file URI";
-Services.scriptloader.loadSubScript(
- "chrome://mochitests/content/browser/devtools/client/netmonitor/test/shared-head.js", this);
-
var hud;
add_task(function* () {
let requests = [];
let { browser } = yield loadTab(TEST_URI);
yield pushPrefEnv();
hud = yield openConsole();
@@ -64,18 +59,16 @@ add_task(function* () {
is(selected.method, htmlRequest.request.method,
"The correct request is selected");
is(selected.url, htmlRequest.request.url,
"The correct request is definitely selected");
// All tests are done. Shutdown.
HUDService.lastFinishedRequest.callback = null;
htmlRequest = browser = requests = hud = null;
-
- yield waitForExistingRequests(monitor);
});
function testMessages() {
return waitForMessages({
webconsole: hud,
messages: [{
text: "running network console logging tests",
category: CATEGORY_WEBDEV,