зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1625909 - Use the ResourceWatcher API to fetch Network Events r=ochameau,Honza,nchevobbe
This patch migrates to using the Resource Watcher API to handle Network events, it adds a legacy listeners for the network events Differential Revision: https://phabricator.services.mozilla.com/D71543
This commit is contained in:
Родитель
185c6d1087
Коммит
9bcb3649ef
|
@ -135,4 +135,4 @@ async function assertResultIsTab(dbg, index) {
|
|||
el && !!el.querySelector(".tab.result-item-icon"),
|
||||
"Result should be a tab"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -742,6 +742,9 @@ Toolbox.prototype = {
|
|||
}
|
||||
},
|
||||
|
||||
_onResourceAvailable() {},
|
||||
_onResourceUpdated() {},
|
||||
|
||||
/**
|
||||
* This method focuses on attaching to one particular target.
|
||||
* It ensure that the target actor is fully initialized and is watching for
|
||||
|
@ -752,10 +755,6 @@ Toolbox.prototype = {
|
|||
async _attachTarget(targetFront) {
|
||||
await targetFront.attach();
|
||||
|
||||
// Start tracking network activity on toolbox open for targets such as tabs.
|
||||
const webConsoleFront = await targetFront.getFront("console");
|
||||
await webConsoleFront.startListeners(["NetworkActivity"]);
|
||||
|
||||
// Do not attach to the thread of additional Frame targets, as they are
|
||||
// already tracked by the content process targets. At least in the context
|
||||
// of the Browser Toolbox.
|
||||
|
@ -843,6 +842,19 @@ Toolbox.prototype = {
|
|||
this._onTargetDestroyed
|
||||
);
|
||||
|
||||
// Start tracking network activity on toolbox open for targets such as tabs.
|
||||
// The listeners attached here do nothing. Doing this just makes sure that
|
||||
// there is always at least one listener existing for network events across
|
||||
// the lifetime of the various panels, so stopping the resource watcher from
|
||||
// clearing out its cache of network event resources.
|
||||
await this.resourceWatcher.watchResources(
|
||||
[this.resourceWatcher.TYPES.NETWORK_EVENT],
|
||||
{
|
||||
onAvailable: this._onResourceAvailable,
|
||||
onUpdated: this._onResourceUpdated,
|
||||
}
|
||||
);
|
||||
|
||||
await domReady;
|
||||
|
||||
this.browserRequire = BrowserLoader({
|
||||
|
@ -3702,6 +3714,14 @@ Toolbox.prototype = {
|
|||
// Reset preferences set by the toolbox
|
||||
outstanding.push(this.resetPreference());
|
||||
|
||||
await this.resourceWatcher.unwatchResources(
|
||||
[this.resourceWatcher.TYPES.NETWORK_EVENT],
|
||||
{
|
||||
onAvailable: this._onResourceAvailable,
|
||||
onUpdated: this._onResourceUpdated,
|
||||
}
|
||||
);
|
||||
|
||||
this.targetList.unwatchTargets(
|
||||
TargetList.ALL_TYPES,
|
||||
this._onTargetAvailable,
|
||||
|
|
|
@ -32,145 +32,32 @@ class WebConsoleFront extends FrontClassWithSpec(webconsoleSpec) {
|
|||
|
||||
// Attribute name from which to retrieve the actorID out of the target actor's form
|
||||
this.formAttributeName = "consoleActor";
|
||||
/**
|
||||
* Holds the network requests currently displayed by the Web Console. Each key
|
||||
* represents the connection ID and the value is network request information.
|
||||
* @private
|
||||
* @type object
|
||||
*/
|
||||
this._networkRequests = new Map();
|
||||
|
||||
this.pendingEvaluationResults = new Map();
|
||||
this.onEvaluationResult = this.onEvaluationResult.bind(this);
|
||||
this.onNetworkEvent = this._onNetworkEvent.bind(this);
|
||||
this.onNetworkEventUpdate = this._onNetworkEventUpdate.bind(this);
|
||||
this._onNetworkEventUpdate = this._onNetworkEventUpdate.bind(this);
|
||||
|
||||
this.on("evaluationResult", this.onEvaluationResult);
|
||||
this.on("serverNetworkEvent", this.onNetworkEvent);
|
||||
this.before("consoleAPICall", this.beforeConsoleAPICall);
|
||||
this.before("pageError", this.beforePageError);
|
||||
|
||||
this._client.on("networkEventUpdate", this.onNetworkEventUpdate);
|
||||
}
|
||||
|
||||
getNetworkRequest(actorId) {
|
||||
return this._networkRequests.get(actorId);
|
||||
}
|
||||
|
||||
getNetworkEvents() {
|
||||
return this._networkRequests.values();
|
||||
this._client.on("networkEventUpdate", this._onNetworkEventUpdate);
|
||||
}
|
||||
|
||||
get actor() {
|
||||
return this.actorID;
|
||||
}
|
||||
|
||||
/**
|
||||
* The "networkEvent" message type handler. We redirect any message to
|
||||
* the UI for displaying.
|
||||
*
|
||||
* @private
|
||||
* @param string type
|
||||
* Message type.
|
||||
* @param object packet
|
||||
* The message received from the server.
|
||||
*/
|
||||
_onNetworkEvent(packet) {
|
||||
const actor = packet.eventActor;
|
||||
const networkInfo = {
|
||||
type: "networkEvent",
|
||||
timeStamp: actor.timeStamp,
|
||||
node: null,
|
||||
actor: actor.actor,
|
||||
discardRequestBody: true,
|
||||
discardResponseBody: true,
|
||||
startedDateTime: actor.startedDateTime,
|
||||
request: {
|
||||
url: actor.url,
|
||||
method: actor.method,
|
||||
},
|
||||
isXHR: actor.isXHR,
|
||||
cause: actor.cause,
|
||||
response: {},
|
||||
timings: {},
|
||||
// track the list of network event updates
|
||||
updates: [],
|
||||
private: actor.private,
|
||||
fromCache: actor.fromCache,
|
||||
fromServiceWorker: actor.fromServiceWorker,
|
||||
isThirdPartyTrackingResource: actor.isThirdPartyTrackingResource,
|
||||
referrerPolicy: actor.referrerPolicy,
|
||||
blockedReason: actor.blockedReason,
|
||||
blockingExtension: actor.blockingExtension,
|
||||
channelId: actor.channelId,
|
||||
};
|
||||
this._networkRequests.set(actor.actor, networkInfo);
|
||||
|
||||
this.emit("networkEvent", networkInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* The "networkEventUpdate" message type handler. We redirect any message to
|
||||
* the UI for displaying.
|
||||
*
|
||||
* @private
|
||||
* @param string type
|
||||
* Message type.
|
||||
* @param object packet
|
||||
* The message received from the server.
|
||||
*/
|
||||
_onNetworkEventUpdate(packet) {
|
||||
const networkInfo = this.getNetworkRequest(packet.from);
|
||||
if (!networkInfo) {
|
||||
return;
|
||||
}
|
||||
|
||||
networkInfo.updates.push(packet.updateType);
|
||||
|
||||
switch (packet.updateType) {
|
||||
case "requestHeaders":
|
||||
networkInfo.request.headersSize = packet.headersSize;
|
||||
break;
|
||||
case "requestPostData":
|
||||
networkInfo.discardRequestBody = packet.discardRequestBody;
|
||||
networkInfo.request.bodySize = packet.dataSize;
|
||||
break;
|
||||
case "responseStart":
|
||||
networkInfo.response.httpVersion = packet.response.httpVersion;
|
||||
networkInfo.response.status = packet.response.status;
|
||||
networkInfo.response.statusText = packet.response.statusText;
|
||||
networkInfo.response.headersSize = packet.response.headersSize;
|
||||
networkInfo.response.remoteAddress = packet.response.remoteAddress;
|
||||
networkInfo.response.remotePort = packet.response.remotePort;
|
||||
networkInfo.discardResponseBody = packet.response.discardResponseBody;
|
||||
networkInfo.response.waitingTime = packet.response.waitingTime;
|
||||
networkInfo.response.content = {
|
||||
mimeType: packet.response.mimeType,
|
||||
};
|
||||
break;
|
||||
case "responseContent":
|
||||
networkInfo.response.content = {
|
||||
mimeType: packet.mimeType,
|
||||
};
|
||||
networkInfo.response.bodySize = packet.contentSize;
|
||||
networkInfo.response.transferredSize = packet.transferredSize;
|
||||
networkInfo.discardResponseBody = packet.discardResponseBody;
|
||||
break;
|
||||
case "eventTimings":
|
||||
networkInfo.totalTime = packet.totalTime;
|
||||
break;
|
||||
case "securityInfo":
|
||||
networkInfo.securityState = packet.state;
|
||||
break;
|
||||
case "responseCache":
|
||||
networkInfo.response.responseCache = packet.responseCache;
|
||||
break;
|
||||
}
|
||||
|
||||
this.emit("networkEventUpdate", {
|
||||
packet: packet,
|
||||
networkInfo,
|
||||
});
|
||||
this.emit("serverNetworkUpdateEvent", packet);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -587,13 +474,6 @@ class WebConsoleFront extends FrontClassWithSpec(webconsoleSpec) {
|
|||
}
|
||||
}
|
||||
|
||||
clearNetworkRequests() {
|
||||
// Prevent exception if the front has already been destroyed.
|
||||
if (this._networkRequests) {
|
||||
this._networkRequests.clear();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Close the WebConsoleFront.
|
||||
*
|
||||
|
@ -603,18 +483,15 @@ class WebConsoleFront extends FrontClassWithSpec(webconsoleSpec) {
|
|||
return null;
|
||||
}
|
||||
|
||||
this._client.off("networkEventUpdate", this.onNetworkEventUpdate);
|
||||
this._client.off("networkEventUpdate", this._onNetworkEventUpdate);
|
||||
// This will make future calls to this function harmless because of the early return
|
||||
// at the top of the function.
|
||||
this._client = null;
|
||||
|
||||
this.off("evaluationResult", this.onEvaluationResult);
|
||||
this.off("serverNetworkEvent", this.onNetworkEvent);
|
||||
this._longStrings = null;
|
||||
this.pendingEvaluationResults.clear();
|
||||
this.pendingEvaluationResults = null;
|
||||
this.clearNetworkRequests();
|
||||
this._networkRequests = null;
|
||||
return super.destroy();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
// panel.
|
||||
|
||||
const TEST_URI =
|
||||
"data:text/html;charset=UTF-8," + "<p>Switch to inspector on pick</p>";
|
||||
"data:text/html;charset=UTF-8,<script>console.log(`hello`)</script><p>Switch to inspector on pick</p>";
|
||||
const ALL_CHANNELS = Ci.nsITelemetry.DATASET_ALL_CHANNELS;
|
||||
|
||||
const DATA = [
|
||||
|
@ -20,7 +20,7 @@ const DATA = [
|
|||
start_state: "initial_panel",
|
||||
panel_name: "webconsole",
|
||||
cold: "true",
|
||||
message_count: "0",
|
||||
message_count: "1",
|
||||
width: "1300",
|
||||
},
|
||||
},
|
||||
|
@ -65,7 +65,7 @@ add_task(async function() {
|
|||
|
||||
await startPickerAndAssertSwitchToInspector(toolbox);
|
||||
|
||||
info("Stoppping element picker.");
|
||||
info("Stopping element picker.");
|
||||
await toolbox.nodePicker.stop();
|
||||
|
||||
checkResults();
|
||||
|
|
|
@ -79,11 +79,6 @@ if (window.location.protocol === "chrome:" && url.search.length > 1) {
|
|||
(async function() {
|
||||
try {
|
||||
const target = await targetFromURL(url);
|
||||
|
||||
// Start the network event listening as it is done in the toolbox code
|
||||
const consoleFront = await target.getFront("console");
|
||||
await consoleFront.startListeners(["NetworkActivity"]);
|
||||
|
||||
// Create a fake toolbox object
|
||||
const toolbox = {
|
||||
target,
|
||||
|
|
|
@ -32,7 +32,6 @@ class FirefoxConnector {
|
|||
this.disconnect = this.disconnect.bind(this);
|
||||
this.willNavigate = this.willNavigate.bind(this);
|
||||
this.navigate = this.navigate.bind(this);
|
||||
this.displayCachedEvents = this.displayCachedEvents.bind(this);
|
||||
this.sendHTTPRequest = this.sendHTTPRequest.bind(this);
|
||||
this.setPreferences = this.setPreferences.bind(this);
|
||||
this.triggerActivity = this.triggerActivity.bind(this);
|
||||
|
@ -44,9 +43,9 @@ class FirefoxConnector {
|
|||
|
||||
// Internals
|
||||
this.getLongString = this.getLongString.bind(this);
|
||||
this.getNetworkRequest = this.getNetworkRequest.bind(this);
|
||||
this.onTargetAvailable = this.onTargetAvailable.bind(this);
|
||||
this.onResourceAvailable = this.onResourceAvailable.bind(this);
|
||||
this.onResourceUpdated = this.onResourceUpdated.bind(this);
|
||||
}
|
||||
|
||||
get currentTarget() {
|
||||
|
@ -114,7 +113,9 @@ class FirefoxConnector {
|
|||
}
|
||||
|
||||
async resume() {
|
||||
await this.addListeners();
|
||||
// On resume, we shoud prevent fetching all cached network events
|
||||
// and only restart recording for the new ones.
|
||||
await this.addListeners(true);
|
||||
}
|
||||
|
||||
async onTargetAvailable({ targetFront, isTargetSwitching }) {
|
||||
|
@ -146,26 +147,35 @@ class FirefoxConnector {
|
|||
|
||||
// Initialize Responsive Emulation front for network throttling.
|
||||
this.responsiveFront = await this.currentTarget.getFront("responsive");
|
||||
|
||||
// Displaying cache events is only intended for the UI panel.
|
||||
if (this.actions) {
|
||||
this.displayCachedEvents();
|
||||
}
|
||||
}
|
||||
|
||||
async onResourceAvailable({ resourceType, targetFront, resource }) {
|
||||
if (resourceType === this.toolbox.resourceWatcher.TYPES.DOCUMENT_EVENT) {
|
||||
const { TYPES } = this.toolbox.resourceWatcher;
|
||||
if (resourceType === TYPES.DOCUMENT_EVENT) {
|
||||
this.onDocEvent(resource);
|
||||
return;
|
||||
}
|
||||
|
||||
if (resourceType === TYPES.NETWORK_EVENT) {
|
||||
this.dataProvider.onNetworkResourceAvailable(resource);
|
||||
}
|
||||
}
|
||||
|
||||
async addListeners() {
|
||||
this.webConsoleFront.on("networkEvent", this.dataProvider.onNetworkEvent);
|
||||
this.webConsoleFront.on(
|
||||
"networkEventUpdate",
|
||||
this.dataProvider.onNetworkEventUpdate
|
||||
);
|
||||
async onResourceUpdated({ resourceType, targetFront, resource }) {
|
||||
if (resourceType === this.toolbox.resourceWatcher.TYPES.NETWORK_EVENT) {
|
||||
this.dataProvider.onNetworkResourceUpdated(resource);
|
||||
}
|
||||
}
|
||||
|
||||
async addListeners(ignoreExistingResources = false) {
|
||||
await this.toolbox.resourceWatcher.watchResources(
|
||||
[this.toolbox.resourceWatcher.TYPES.NETWORK_EVENT],
|
||||
{
|
||||
onAvailable: this.onResourceAvailable,
|
||||
onUpdated: this.onResourceUpdated,
|
||||
ignoreExistingResources,
|
||||
}
|
||||
);
|
||||
// Support for WebSocket monitoring is currently hidden behind this pref.
|
||||
if (Services.prefs.getBoolPref("devtools.netmonitor.features.webSockets")) {
|
||||
try {
|
||||
|
@ -206,6 +216,13 @@ class FirefoxConnector {
|
|||
}
|
||||
|
||||
removeListeners() {
|
||||
this.toolbox.resourceWatcher.unwatchResources(
|
||||
[this.toolbox.resourceWatcher.TYPES.NETWORK_EVENT],
|
||||
{
|
||||
onAvailable: this.onResourceAvailable,
|
||||
onUpdated: this.onResourceUpdated,
|
||||
}
|
||||
);
|
||||
const webSocketFront = this.currentTarget.getCachedFront("webSocket");
|
||||
if (webSocketFront) {
|
||||
webSocketFront.off(
|
||||
|
@ -220,17 +237,6 @@ class FirefoxConnector {
|
|||
webSocketFront.off("frameSent", this.dataProvider.onFrameSent);
|
||||
}
|
||||
|
||||
if (this.webConsoleFront) {
|
||||
this.webConsoleFront.off(
|
||||
"networkEvent",
|
||||
this.dataProvider.onNetworkEvent
|
||||
);
|
||||
this.webConsoleFront.off(
|
||||
"networkEventUpdate",
|
||||
this.dataProvider.onNetworkEventUpdate
|
||||
);
|
||||
}
|
||||
|
||||
const eventSourceFront = this.currentTarget.getCachedFront("eventSource");
|
||||
if (eventSourceFront) {
|
||||
eventSourceFront.off(
|
||||
|
@ -300,23 +306,6 @@ class FirefoxConnector {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Display any network events already in the cache.
|
||||
*/
|
||||
displayCachedEvents() {
|
||||
for (const networkInfo of this.webConsoleFront.getNetworkEvents()) {
|
||||
// First add the request to the timeline.
|
||||
this.dataProvider.onNetworkEvent(networkInfo);
|
||||
// Then replay any updates already received.
|
||||
for (const updateType of networkInfo.updates) {
|
||||
this.dataProvider.onNetworkEventUpdate({
|
||||
packet: { updateType },
|
||||
networkInfo,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The "DOMContentLoaded" and "Load" events sent by the console actor.
|
||||
*
|
||||
|
@ -465,16 +454,6 @@ class FirefoxConnector {
|
|||
return Promise.reject(new Error("Invalid activity type"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches the network information packet from actor server
|
||||
*
|
||||
* @param {string} id request id
|
||||
* @return {object} networkInfo data packet
|
||||
*/
|
||||
getNetworkRequest(id) {
|
||||
return this.dataProvider.getNetworkRequest(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches the full text of a LongString.
|
||||
*
|
||||
|
|
|
@ -48,8 +48,10 @@ class FirefoxDataProvider {
|
|||
this.getLongString = this.getLongString.bind(this);
|
||||
|
||||
// Event handlers
|
||||
this.onNetworkEvent = this.onNetworkEvent.bind(this);
|
||||
this.onNetworkEventUpdate = this.onNetworkEventUpdate.bind(this);
|
||||
this.onNetworkResourceAvailable = this.onNetworkResourceAvailable.bind(
|
||||
this
|
||||
);
|
||||
this.onNetworkResourceUpdated = this.onNetworkResourceUpdated.bind(this);
|
||||
|
||||
this.onWebSocketOpened = this.onWebSocketOpened.bind(this);
|
||||
this.onWebSocketClosed = this.onWebSocketClosed.bind(this);
|
||||
|
@ -79,50 +81,26 @@ class FirefoxDataProvider {
|
|||
* @param {object} data data payload will be added to application state
|
||||
*/
|
||||
async addRequest(id, data) {
|
||||
const {
|
||||
method,
|
||||
url,
|
||||
isXHR,
|
||||
cause,
|
||||
startedDateTime,
|
||||
fromCache,
|
||||
fromServiceWorker,
|
||||
isThirdPartyTrackingResource,
|
||||
referrerPolicy,
|
||||
blockedReason,
|
||||
blockingExtension,
|
||||
channelId,
|
||||
} = data;
|
||||
const { startedDateTime, ...payload } = data;
|
||||
|
||||
// Insert blocked reason in the payload queue as well, as we'll need it later
|
||||
// when deciding if the request is complete.
|
||||
this.pushRequestToQueue(id, {
|
||||
blockedReason,
|
||||
blockedReason: payload.blockedReason,
|
||||
});
|
||||
|
||||
if (this.actionsEnabled && this.actions.addRequest) {
|
||||
await this.actions.addRequest(
|
||||
id,
|
||||
{
|
||||
...payload,
|
||||
// Convert the received date/time string to a unix timestamp.
|
||||
startedMs: Date.parse(startedDateTime),
|
||||
method,
|
||||
url,
|
||||
isXHR,
|
||||
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,
|
||||
isThirdPartyTrackingResource,
|
||||
referrerPolicy,
|
||||
blockedReason,
|
||||
blockingExtension,
|
||||
channelId,
|
||||
stacktrace: payload.cause.stacktrace,
|
||||
},
|
||||
true
|
||||
);
|
||||
|
@ -324,16 +302,6 @@ class FirefoxDataProvider {
|
|||
Object.assign(payloadFromQueue, payload);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches the network information packet from actor server
|
||||
*
|
||||
* @param {string} id request id
|
||||
* @return {object} networkInfo data packet
|
||||
*/
|
||||
getNetworkRequest(id) {
|
||||
return this.webConsoleFront.getNetworkRequest(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches the full text of a LongString.
|
||||
*
|
||||
|
@ -353,11 +321,11 @@ class FirefoxDataProvider {
|
|||
}
|
||||
|
||||
/**
|
||||
* The "networkEvent" message type handler.
|
||||
* The handler for when the network event resource is available.
|
||||
*
|
||||
* @param {object} networkInfo network request information
|
||||
* @param {object} resource The network event resource
|
||||
*/
|
||||
async onNetworkEvent(networkInfo) {
|
||||
async onNetworkResourceAvailable(resource) {
|
||||
const {
|
||||
actor,
|
||||
cause,
|
||||
|
@ -365,13 +333,34 @@ class FirefoxDataProvider {
|
|||
fromServiceWorker,
|
||||
isXHR,
|
||||
request: { method, url },
|
||||
response: { bodySize, ...responseProps },
|
||||
startedDateTime,
|
||||
isThirdPartyTrackingResource,
|
||||
referrerPolicy,
|
||||
blockedReason,
|
||||
blockingExtension,
|
||||
channelId,
|
||||
} = networkInfo;
|
||||
} = resource;
|
||||
|
||||
// For resources from the resource watcher cache no updates are going to be fired
|
||||
// as the resource already contains all the updated props. These need to be set so
|
||||
// the UI knows the data is available on the backend.
|
||||
const available = {};
|
||||
[
|
||||
"eventTimings",
|
||||
"requestHeaders",
|
||||
"requestPostData",
|
||||
"responseHeaders",
|
||||
"responseStart",
|
||||
"responseContent",
|
||||
"securityInfo",
|
||||
"responseCache",
|
||||
"responseCookies",
|
||||
].forEach(updateType => {
|
||||
if (resource.updates.includes(updateType)) {
|
||||
available[`${updateType}Available`] = true;
|
||||
}
|
||||
});
|
||||
|
||||
await this.addRequest(actor, {
|
||||
cause,
|
||||
|
@ -386,56 +375,55 @@ class FirefoxDataProvider {
|
|||
blockedReason,
|
||||
blockingExtension,
|
||||
channelId,
|
||||
mimeType: resource?.content?.mimeType,
|
||||
contentSize: bodySize,
|
||||
...responseProps,
|
||||
...available,
|
||||
});
|
||||
|
||||
this.emitForTests(TEST_EVENTS.NETWORK_EVENT, actor);
|
||||
this.emitForTests(TEST_EVENTS.NETWORK_EVENT, resource);
|
||||
}
|
||||
|
||||
/**
|
||||
* The "networkEventUpdate" message type handler.
|
||||
* The handler for when the network event resource is updated.
|
||||
*
|
||||
* @param {object} packet the message received from the server.
|
||||
* @param {object} networkInfo the network request information.
|
||||
* @param {object} resource The updated network event resource.
|
||||
*/
|
||||
async onNetworkEventUpdate(data) {
|
||||
const { packet, networkInfo } = data;
|
||||
const { actor } = networkInfo;
|
||||
const { updateType } = packet;
|
||||
|
||||
switch (updateType) {
|
||||
async onNetworkResourceUpdated(resource) {
|
||||
switch (resource.updateType) {
|
||||
case "securityInfo":
|
||||
this.pushRequestToQueue(actor, {
|
||||
securityState: networkInfo.securityState,
|
||||
isRacing: packet.isRacing,
|
||||
this.pushRequestToQueue(resource.actor, {
|
||||
securityState: resource.securityState,
|
||||
isRacing: resource.isRacing,
|
||||
});
|
||||
break;
|
||||
case "responseStart":
|
||||
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,
|
||||
waitingTime: networkInfo.response.waitingTime,
|
||||
this.pushRequestToQueue(resource.actor, {
|
||||
httpVersion: resource.response.httpVersion,
|
||||
remoteAddress: resource.response.remoteAddress,
|
||||
remotePort: resource.response.remotePort,
|
||||
status: resource.response.status,
|
||||
statusText: resource.response.statusText,
|
||||
headersSize: resource.response.headersSize,
|
||||
waitingTime: resource.response.waitingTime,
|
||||
});
|
||||
|
||||
// Identify the channel as SSE if mimeType is event-stream.
|
||||
if (
|
||||
networkInfo.response.content.mimeType?.includes("text/event-stream")
|
||||
) {
|
||||
await this.setEventStreamFlag(actor);
|
||||
if (resource.response.content.mimeType?.includes("text/event-stream")) {
|
||||
await this.setEventStreamFlag(resource.actor);
|
||||
}
|
||||
|
||||
this.emitForTests(TEST_EVENTS.STARTED_RECEIVING_RESPONSE, actor);
|
||||
this.emitForTests(
|
||||
TEST_EVENTS.STARTED_RECEIVING_RESPONSE,
|
||||
resource.actor
|
||||
);
|
||||
break;
|
||||
case "responseContent":
|
||||
this.pushRequestToQueue(actor, {
|
||||
contentSize: networkInfo.response.bodySize,
|
||||
transferredSize: networkInfo.response.transferredSize,
|
||||
mimeType: networkInfo.response.content.mimeType,
|
||||
blockingExtension: packet.blockingExtension,
|
||||
blockedReason: packet.blockedReason,
|
||||
this.pushRequestToQueue(resource.actor, {
|
||||
contentSize: resource.response.bodySize,
|
||||
transferredSize: resource.response.transferredSize,
|
||||
mimeType: resource.response.content.mimeType,
|
||||
blockingExtension: resource.blockingExtension,
|
||||
blockedReason: resource.blockedReason,
|
||||
});
|
||||
break;
|
||||
case "eventTimings":
|
||||
|
@ -443,19 +431,23 @@ class FirefoxDataProvider {
|
|||
// in Console panel is using this method to fetch data when network log
|
||||
// is expanded. So, make sure to not push undefined into the payload queue
|
||||
// (it could overwrite an existing value).
|
||||
if (typeof networkInfo.totalTime !== "undefined") {
|
||||
this.pushRequestToQueue(actor, { totalTime: networkInfo.totalTime });
|
||||
if (typeof resource.totalTime !== "undefined") {
|
||||
this.pushRequestToQueue(resource.actor, {
|
||||
totalTime: resource.totalTime,
|
||||
});
|
||||
}
|
||||
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.pushRequestToQueue(resource.actor, {
|
||||
[`${resource.updateType}Available`]: true,
|
||||
});
|
||||
|
||||
await this.onPayloadDataReceived(actor);
|
||||
await this.onPayloadDataReceived(resource);
|
||||
|
||||
this.emitForTests(TEST_EVENTS.NETWORK_EVENT_UPDATED, actor);
|
||||
this.emitForTests(TEST_EVENTS.NETWORK_EVENT_UPDATED, resource.actor);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -516,14 +508,14 @@ class FirefoxDataProvider {
|
|||
}
|
||||
|
||||
/**
|
||||
* Notify actions when messages from onNetworkEventUpdate are done, networkEventUpdate
|
||||
* messages contain initial network info for each updateType and then we can invoke
|
||||
* Notify actions when events from onNetworkResourceUpdated are done, updated network event
|
||||
* resources 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.
|
||||
* Once all updateTypes of updated network event resource are available, we flush the merged
|
||||
* request payload from pending queue and then update the component.
|
||||
*/
|
||||
async onPayloadDataReceived(actor) {
|
||||
const payload = this.payloadQueue.get(actor) || {};
|
||||
async onPayloadDataReceived(resource) {
|
||||
const payload = this.payloadQueue.get(resource.actor) || {};
|
||||
|
||||
// For blocked requests, we should only expect the request portions and not
|
||||
// the response portions to be available.
|
||||
|
@ -538,17 +530,17 @@ class FirefoxDataProvider {
|
|||
return;
|
||||
}
|
||||
|
||||
this.payloadQueue.delete(actor);
|
||||
this.payloadQueue.delete(resource.actor);
|
||||
|
||||
if (this.actionsEnabled && this.actions.updateRequest) {
|
||||
await this.actions.updateRequest(actor, payload, true);
|
||||
await this.actions.updateRequest(resource.actor, payload, 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.
|
||||
// from `onNetworkResourceUpdated`. There should be no more RDP requests after this.
|
||||
// Note that this event might be consumed by extension so, emit it in production
|
||||
// release as well.
|
||||
this.emit(EVENTS.PAYLOAD_READY, actor);
|
||||
this.emit(EVENTS.PAYLOAD_READY, resource);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -674,7 +666,7 @@ class FirefoxDataProvider {
|
|||
const payload = await this.updateRequest(response.from, {
|
||||
requestHeaders: response,
|
||||
});
|
||||
this.emitForTests(TEST_EVENTS.RECEIVED_REQUEST_HEADERS, response.from);
|
||||
this.emitForTests(TEST_EVENTS.RECEIVED_REQUEST_HEADERS, response);
|
||||
return payload.requestHeaders;
|
||||
}
|
||||
|
||||
|
@ -687,7 +679,7 @@ class FirefoxDataProvider {
|
|||
const payload = await this.updateRequest(response.from, {
|
||||
responseHeaders: response,
|
||||
});
|
||||
this.emitForTests(TEST_EVENTS.RECEIVED_RESPONSE_HEADERS, response.from);
|
||||
this.emitForTests(TEST_EVENTS.RECEIVED_RESPONSE_HEADERS, response);
|
||||
return payload.responseHeaders;
|
||||
}
|
||||
|
||||
|
@ -700,7 +692,7 @@ class FirefoxDataProvider {
|
|||
const payload = await this.updateRequest(response.from, {
|
||||
requestCookies: response,
|
||||
});
|
||||
this.emitForTests(TEST_EVENTS.RECEIVED_REQUEST_COOKIES, response.from);
|
||||
this.emitForTests(TEST_EVENTS.RECEIVED_REQUEST_COOKIES, response);
|
||||
return payload.requestCookies;
|
||||
}
|
||||
|
||||
|
@ -713,7 +705,7 @@ class FirefoxDataProvider {
|
|||
const payload = await this.updateRequest(response.from, {
|
||||
requestPostData: response,
|
||||
});
|
||||
this.emitForTests(TEST_EVENTS.RECEIVED_REQUEST_POST_DATA, response.from);
|
||||
this.emitForTests(TEST_EVENTS.RECEIVED_REQUEST_POST_DATA, response);
|
||||
return payload.requestPostData;
|
||||
}
|
||||
|
||||
|
@ -726,7 +718,7 @@ class FirefoxDataProvider {
|
|||
const payload = await this.updateRequest(response.from, {
|
||||
securityInfo: response.securityInfo,
|
||||
});
|
||||
this.emitForTests(TEST_EVENTS.RECEIVED_SECURITY_INFO, response.from);
|
||||
this.emitForTests(TEST_EVENTS.RECEIVED_SECURITY_INFO, response);
|
||||
return payload.securityInfo;
|
||||
}
|
||||
|
||||
|
@ -739,7 +731,7 @@ class FirefoxDataProvider {
|
|||
const payload = await this.updateRequest(response.from, {
|
||||
responseCookies: response,
|
||||
});
|
||||
this.emitForTests(TEST_EVENTS.RECEIVED_RESPONSE_COOKIES, response.from);
|
||||
this.emitForTests(TEST_EVENTS.RECEIVED_RESPONSE_COOKIES, response);
|
||||
return payload.responseCookies;
|
||||
}
|
||||
|
||||
|
@ -751,7 +743,7 @@ class FirefoxDataProvider {
|
|||
const payload = await this.updateRequest(response.from, {
|
||||
responseCache: response,
|
||||
});
|
||||
this.emitForTests(TEST_EVENTS.RECEIVED_RESPONSE_CACHE, response.from);
|
||||
this.emitForTests(TEST_EVENTS.RECEIVED_RESPONSE_CACHE, response);
|
||||
return payload.responseCache;
|
||||
}
|
||||
|
||||
|
@ -768,7 +760,7 @@ class FirefoxDataProvider {
|
|||
mimeType: response.content.mimeType,
|
||||
responseContent: response,
|
||||
});
|
||||
this.emitForTests(TEST_EVENTS.RECEIVED_RESPONSE_CONTENT, response.from);
|
||||
this.emitForTests(TEST_EVENTS.RECEIVED_RESPONSE_CONTENT, response);
|
||||
return payload.responseContent;
|
||||
}
|
||||
|
||||
|
@ -786,7 +778,7 @@ class FirefoxDataProvider {
|
|||
// and running DAMP test doesn't set the `devtools.testing` flag.
|
||||
// So, emit this event even in the production mode.
|
||||
// See also: https://bugzilla.mozilla.org/show_bug.cgi?id=1578215
|
||||
this.emit(EVENTS.RECEIVED_EVENT_TIMINGS, response.from);
|
||||
this.emit(EVENTS.RECEIVED_EVENT_TIMINGS, response);
|
||||
return payload.eventTimings;
|
||||
}
|
||||
|
||||
|
@ -799,7 +791,7 @@ class FirefoxDataProvider {
|
|||
const payload = await this.updateRequest(response.from, {
|
||||
stacktrace: response.stacktrace,
|
||||
});
|
||||
this.emitForTests(TEST_EVENTS.RECEIVED_EVENT_STACKTRACE, response.from);
|
||||
this.emitForTests(TEST_EVENTS.RECEIVED_EVENT_STACKTRACE, response);
|
||||
return payload.stacktrace;
|
||||
}
|
||||
|
||||
|
|
|
@ -19,7 +19,6 @@ class Connector {
|
|||
this.connectChrome = this.connectChrome.bind(this);
|
||||
this.connectFirefox = this.connectFirefox.bind(this);
|
||||
this.getLongString = this.getLongString.bind(this);
|
||||
this.getNetworkRequest = this.getNetworkRequest.bind(this);
|
||||
this.getTabTarget = this.getTabTarget.bind(this);
|
||||
this.sendHTTPRequest = this.sendHTTPRequest.bind(this);
|
||||
this.setPreferences = this.setPreferences.bind(this);
|
||||
|
@ -84,10 +83,6 @@ class Connector {
|
|||
return this.connector.getLongString(...arguments);
|
||||
}
|
||||
|
||||
getNetworkRequest() {
|
||||
return this.connector.getNetworkRequest(...arguments);
|
||||
}
|
||||
|
||||
getTabTarget() {
|
||||
return this.connector.getTabTarget();
|
||||
}
|
||||
|
|
|
@ -88,7 +88,7 @@ HarAutomation.prototype = {
|
|||
// data from events sent from the backend.
|
||||
this.collector = new HarCollector({
|
||||
webConsoleFront: this.webConsoleFront,
|
||||
devToolsClient: this.devToolsClient,
|
||||
resourceWatcher: this.toolbox.resourceWatcher,
|
||||
});
|
||||
|
||||
this.collector.start();
|
||||
|
|
|
@ -17,10 +17,10 @@ const trace = {
|
|||
*/
|
||||
function HarCollector(options) {
|
||||
this.webConsoleFront = options.webConsoleFront;
|
||||
this.devToolsClient = options.devToolsClient;
|
||||
this.resourceWatcher = options.resourceWatcher;
|
||||
|
||||
this.onNetworkEvent = this.onNetworkEvent.bind(this);
|
||||
this.onNetworkEventUpdate = this.onNetworkEventUpdate.bind(this);
|
||||
this.onResourceAvailable = this.onResourceAvailable.bind(this);
|
||||
this.onResourceUpdated = this.onResourceUpdated.bind(this);
|
||||
this.onRequestHeaders = this.onRequestHeaders.bind(this);
|
||||
this.onRequestCookies = this.onRequestCookies.bind(this);
|
||||
this.onRequestPostData = this.onRequestPostData.bind(this);
|
||||
|
@ -35,14 +35,24 @@ function HarCollector(options) {
|
|||
HarCollector.prototype = {
|
||||
// Connection
|
||||
|
||||
start: function() {
|
||||
this.webConsoleFront.on("networkEvent", this.onNetworkEvent);
|
||||
this.devToolsClient.on("networkEventUpdate", this.onNetworkEventUpdate);
|
||||
start: async function() {
|
||||
await this.resourceWatcher.watchResources(
|
||||
[this.resourceWatcher.TYPES.NETWORK_EVENT],
|
||||
{
|
||||
onAvailable: this.onResourceAvailable,
|
||||
onUpdated: this.onResourceUpdated,
|
||||
}
|
||||
);
|
||||
},
|
||||
|
||||
stop: function() {
|
||||
this.webConsoleFront.off("networkEvent", this.onNetworkEvent);
|
||||
this.devToolsClient.off("networkEventUpdate", this.onNetworkEventUpdate);
|
||||
stop: async function() {
|
||||
await this.resourceWatcher.unwatchResources(
|
||||
[this.resourceWatcher.TYPES.NETWORK_EVENT],
|
||||
{
|
||||
onAvailable: this.onResourceAvailable,
|
||||
onUpdated: this.onResourceUpdated,
|
||||
}
|
||||
);
|
||||
},
|
||||
|
||||
clear: function() {
|
||||
|
@ -156,15 +166,15 @@ HarCollector.prototype = {
|
|||
|
||||
// Event Handlers
|
||||
|
||||
onNetworkEvent: function(packet) {
|
||||
trace.log("HarCollector.onNetworkEvent; ", packet);
|
||||
onResourceAvailable: function({ resourceType, targetFront, resource }) {
|
||||
trace.log("HarCollector.onNetworkEvent; ", resource);
|
||||
|
||||
const {
|
||||
actor,
|
||||
startedDateTime,
|
||||
request: { method, url },
|
||||
isXHR,
|
||||
} = packet;
|
||||
} = resource;
|
||||
const startTime = Date.parse(startedDateTime);
|
||||
|
||||
if (this.firstRequestStart == -1) {
|
||||
|
@ -198,21 +208,19 @@ HarCollector.prototype = {
|
|||
this.items.push(file);
|
||||
},
|
||||
|
||||
onNetworkEventUpdate: function(packet) {
|
||||
const actor = packet.from;
|
||||
|
||||
onResourceUpdated: function({ resourceType, targetFront, resource }) {
|
||||
// Skip events from unknown actors (not in the list).
|
||||
// It can happen when there are zombie requests received after
|
||||
// the target is closed or multiple tabs are attached through
|
||||
// one connection (one DevToolsClient object).
|
||||
const file = this.getFile(packet.from);
|
||||
const file = this.getFile(resource.actor);
|
||||
if (!file) {
|
||||
return;
|
||||
}
|
||||
|
||||
trace.log(
|
||||
"HarCollector.onNetworkEventUpdate; " + packet.updateType,
|
||||
packet
|
||||
"HarCollector.onNetworkEventUpdate; " + resource.updateType,
|
||||
resource
|
||||
);
|
||||
|
||||
const includeResponseBodies = Services.prefs.getBoolPref(
|
||||
|
@ -220,62 +228,66 @@ HarCollector.prototype = {
|
|||
);
|
||||
|
||||
let request;
|
||||
switch (packet.updateType) {
|
||||
switch (resource.updateType) {
|
||||
case "requestHeaders":
|
||||
request = this.getData(
|
||||
actor,
|
||||
resource.actor,
|
||||
"getRequestHeaders",
|
||||
this.onRequestHeaders
|
||||
);
|
||||
break;
|
||||
case "requestCookies":
|
||||
request = this.getData(
|
||||
actor,
|
||||
resource.actor,
|
||||
"getRequestCookies",
|
||||
this.onRequestCookies
|
||||
);
|
||||
break;
|
||||
case "requestPostData":
|
||||
request = this.getData(
|
||||
actor,
|
||||
resource.actor,
|
||||
"getRequestPostData",
|
||||
this.onRequestPostData
|
||||
);
|
||||
break;
|
||||
case "responseHeaders":
|
||||
request = this.getData(
|
||||
actor,
|
||||
resource.actor,
|
||||
"getResponseHeaders",
|
||||
this.onResponseHeaders
|
||||
);
|
||||
break;
|
||||
case "responseCookies":
|
||||
request = this.getData(
|
||||
actor,
|
||||
resource.actor,
|
||||
"getResponseCookies",
|
||||
this.onResponseCookies
|
||||
);
|
||||
break;
|
||||
case "responseStart":
|
||||
file.httpVersion = packet.response.httpVersion;
|
||||
file.status = packet.response.status;
|
||||
file.statusText = packet.response.statusText;
|
||||
file.httpVersion = resource.response.httpVersion;
|
||||
file.status = resource.response.status;
|
||||
file.statusText = resource.response.statusText;
|
||||
break;
|
||||
case "responseContent":
|
||||
file.contentSize = packet.contentSize;
|
||||
file.mimeType = packet.mimeType;
|
||||
file.transferredSize = packet.transferredSize;
|
||||
file.contentSize = resource.contentSize;
|
||||
file.mimeType = resource.mimeType;
|
||||
file.transferredSize = resource.transferredSize;
|
||||
|
||||
if (includeResponseBodies) {
|
||||
request = this.getData(
|
||||
actor,
|
||||
resource.actor,
|
||||
"getResponseContent",
|
||||
this.onResponseContent
|
||||
);
|
||||
}
|
||||
break;
|
||||
case "eventTimings":
|
||||
request = this.getData(actor, "getEventTimings", this.onEventTimings);
|
||||
request = this.getData(
|
||||
resource.actor,
|
||||
"getEventTimings",
|
||||
this.onEventTimings
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -82,7 +82,7 @@ async function performRequestAndWait(tab, monitor) {
|
|||
* Execute simple GET request
|
||||
*/
|
||||
async function performPausedRequest(connector, tab, monitor) {
|
||||
const wait = connector.connector.webConsoleFront.once("networkEvent");
|
||||
const wait = connector.connector.webConsoleFront.once("serverNetworkEvent");
|
||||
await SpecialPowers.spawn(tab.linkedBrowser, [SIMPLE_SJS], async function(
|
||||
url
|
||||
) {
|
||||
|
|
|
@ -265,8 +265,8 @@ function startNetworkEventUpdateObserver(panelWin) {
|
|||
);
|
||||
|
||||
updatedTypes.forEach(type =>
|
||||
panelWin.api.on(type, actor => {
|
||||
const key = actor + "-" + type;
|
||||
panelWin.api.on(type, payload => {
|
||||
const key = payload.from + "-" + type;
|
||||
finishedQueue[key] = finishedQueue[key] ? finishedQueue[key] - 1 : -1;
|
||||
})
|
||||
);
|
||||
|
@ -279,7 +279,6 @@ async function waitForAllNetworkUpdateEvents() {
|
|||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
info("Wait for completion of all NetworkUpdateEvents packets...");
|
||||
|
@ -331,23 +330,7 @@ function initNetMonitor(url, { requestCount, enableCache = false }) {
|
|||
const markersDone = waitForTimelineMarkers(monitor);
|
||||
await toggleCache(target, true);
|
||||
await Promise.all([requestsDone, markersDone]);
|
||||
info(
|
||||
"Cache disabled when the current and all future toolboxes are open."
|
||||
);
|
||||
|
||||
const consoleFront = await target.getFront("console");
|
||||
|
||||
// Remove any requests generated by the reload while toggling the cache to
|
||||
// avoid interfering with the test.
|
||||
isnot(
|
||||
[...consoleFront.getNetworkEvents()].length,
|
||||
0,
|
||||
"Request to reconfigure the tab was recorded."
|
||||
);
|
||||
info("Clearing requests in the console client.");
|
||||
await consoleFront.clearNetworkRequests();
|
||||
info("Clearing requests in the UI.");
|
||||
|
||||
store.dispatch(Actions.clearRequests());
|
||||
}
|
||||
|
||||
|
@ -397,50 +380,31 @@ function isFiltering(monitor) {
|
|||
function waitForNetworkEvents(monitor, getRequests) {
|
||||
return new Promise(resolve => {
|
||||
const panel = monitor.panelWin;
|
||||
const { getNetworkRequest } = panel.connector;
|
||||
let networkEvent = 0;
|
||||
let nonBlockedNetworkEvent = 0;
|
||||
let payloadReady = 0;
|
||||
let eventTimings = 0;
|
||||
const filtering = isFiltering(monitor);
|
||||
|
||||
function onNetworkEvent(actor) {
|
||||
const networkInfo = getNetworkRequest(actor);
|
||||
if (!networkInfo) {
|
||||
// Must have been related to reloading document to disable cache.
|
||||
// Ignore the event.
|
||||
return;
|
||||
}
|
||||
function onNetworkEvent(resource) {
|
||||
networkEvent++;
|
||||
if (!networkInfo.blockedReason) {
|
||||
if (!resource.blockedReason) {
|
||||
nonBlockedNetworkEvent++;
|
||||
}
|
||||
maybeResolve(TEST_EVENTS.NETWORK_EVENT, actor, networkInfo);
|
||||
maybeResolve(TEST_EVENTS.NETWORK_EVENT, resource.actor);
|
||||
}
|
||||
|
||||
function onPayloadReady(actor) {
|
||||
const networkInfo = getNetworkRequest(actor);
|
||||
if (!networkInfo) {
|
||||
// Must have been related to reloading document to disable cache.
|
||||
// Ignore the event.
|
||||
return;
|
||||
}
|
||||
function onPayloadReady(resource) {
|
||||
payloadReady++;
|
||||
maybeResolve(EVENTS.PAYLOAD_READY, actor, networkInfo);
|
||||
maybeResolve(EVENTS.PAYLOAD_READY, resource.actor);
|
||||
}
|
||||
|
||||
function onEventTimings(actor) {
|
||||
const networkInfo = getNetworkRequest(actor);
|
||||
if (!networkInfo) {
|
||||
// Must have been related to reloading document to disable cache.
|
||||
// Ignore the event.
|
||||
return;
|
||||
}
|
||||
function onEventTimings(response) {
|
||||
eventTimings++;
|
||||
maybeResolve(EVENTS.RECEIVED_EVENT_TIMINGS, actor, networkInfo);
|
||||
maybeResolve(EVENTS.RECEIVED_EVENT_TIMINGS, response.from);
|
||||
}
|
||||
|
||||
function maybeResolve(event, actor, networkInfo) {
|
||||
function maybeResolve(event, actor) {
|
||||
info(
|
||||
"> Network event progress: " +
|
||||
"NetworkEvent: " +
|
||||
|
|
|
@ -146,7 +146,7 @@ function messageRemove(id) {
|
|||
};
|
||||
}
|
||||
|
||||
function networkMessageUpdate(packet, idGenerator = null, response) {
|
||||
function networkMessageUpdate(packet, idGenerator = null) {
|
||||
if (idGenerator == null) {
|
||||
idGenerator = defaultIdGenerator;
|
||||
}
|
||||
|
@ -156,7 +156,6 @@ function networkMessageUpdate(packet, idGenerator = null, response) {
|
|||
return {
|
||||
type: NETWORK_MESSAGE_UPDATE,
|
||||
message,
|
||||
response,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -175,7 +175,6 @@ function NetworkEventMessage({
|
|||
return serviceContainer.getLongString(grip);
|
||||
},
|
||||
getTabTarget: () => {},
|
||||
getNetworkRequest: () => {},
|
||||
sendHTTPRequest: () => {},
|
||||
setPreferences: () => {},
|
||||
triggerActivity: () => {},
|
||||
|
|
|
@ -17,7 +17,6 @@ function enableMessagesCacheClearing(webConsoleUI) {
|
|||
state = reducer(state, action);
|
||||
|
||||
if (webConsoleUI && action.type === MESSAGES_CLEAR) {
|
||||
webConsoleUI.clearNetworkRequests();
|
||||
webConsoleUI.clearMessagesCache();
|
||||
}
|
||||
return state;
|
||||
|
|
|
@ -50,12 +50,9 @@ function enableNetProvider(webConsoleUI) {
|
|||
const updates = getAllNetworkMessagesUpdateById(newState);
|
||||
const message = updates[action.id];
|
||||
if (message && !message.openedOnce && message.source == "network") {
|
||||
dataProvider.onNetworkEvent(message);
|
||||
dataProvider.onNetworkResourceAvailable(message);
|
||||
message.updates.forEach(updateType => {
|
||||
dataProvider.onNetworkEventUpdate({
|
||||
packet: { updateType: updateType },
|
||||
networkInfo: message,
|
||||
});
|
||||
dataProvider.onNetworkResourceUpdated({ ...message, updateType });
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -64,18 +61,15 @@ function enableNetProvider(webConsoleUI) {
|
|||
// Network event update packets are sent in batches from:
|
||||
// `WebConsoleOutputWrapper.dispatchMessageUpdate` using
|
||||
// NETWORK_MESSAGE_UPDATE action.
|
||||
// Make sure to call `dataProvider.onNetworkEventUpdate`
|
||||
// Make sure to call `dataProvider.onNetworkResourceUpdated`
|
||||
// to fetch data from the backend.
|
||||
if (type == NETWORK_MESSAGE_UPDATE) {
|
||||
const { actor } = action.response.networkInfo;
|
||||
const { actor } = action.message;
|
||||
const open = getAllMessagesUiById(state).includes(actor);
|
||||
if (open) {
|
||||
const message = getMessage(state, actor);
|
||||
message.updates.forEach(updateType => {
|
||||
dataProvider.onNetworkEventUpdate({
|
||||
packet: { updateType },
|
||||
networkInfo: message,
|
||||
});
|
||||
dataProvider.onNetworkResourceUpdated({ ...message, updateType });
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -60,15 +60,18 @@ add_task(async function task() {
|
|||
async function testNetmonitor(toolbox) {
|
||||
const monitor = toolbox.getCurrentPanel();
|
||||
|
||||
const { store, windowRequire } = monitor.panelWin;
|
||||
const { document, store, windowRequire } = monitor.panelWin;
|
||||
const Actions = windowRequire("devtools/client/netmonitor/src/actions/index");
|
||||
const { getSortedRequests } = windowRequire(
|
||||
"devtools/client/netmonitor/src/selectors/index"
|
||||
);
|
||||
|
||||
store.dispatch(Actions.batchEnable(false));
|
||||
|
||||
const requestItem = document.querySelector(".request-list-item");
|
||||
await waitUntil(() => store.getState().requests.requests.length > 0);
|
||||
// Lets also wait until all the event timings data requested
|
||||
// has completed and the column is rendered.
|
||||
await waitForDOM(requestItem, ".requests-list-timings-total");
|
||||
|
||||
is(
|
||||
store.getState().requests.requests.length,
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
"use strict";
|
||||
|
||||
const {
|
||||
createResourceWatcherForTab,
|
||||
STUBS_UPDATE_ENV,
|
||||
getStubFile,
|
||||
getCleanedPacket,
|
||||
|
@ -62,31 +63,52 @@ add_task(async function() {
|
|||
});
|
||||
|
||||
async function generateNetworkEventStubs() {
|
||||
const packets = new Map();
|
||||
const toolbox = await openNewTabAndToolbox(TEST_URI, "webconsole");
|
||||
const { ui } = toolbox.getCurrentPanel().hud;
|
||||
const stubs = new Map();
|
||||
const tab = await addTab(TEST_URI);
|
||||
const resourceWatcher = await createResourceWatcherForTab(tab);
|
||||
|
||||
let addNetworkStub = function() {};
|
||||
let addNetworkUpdateStub = function() {};
|
||||
|
||||
const onAvailable = resource => {
|
||||
addNetworkStub(resource);
|
||||
};
|
||||
const onUpdated = resource => {
|
||||
addNetworkUpdateStub(resource);
|
||||
};
|
||||
|
||||
await resourceWatcher.watchResources([resourceWatcher.TYPES.NETWORK_EVENT], {
|
||||
onAvailable,
|
||||
onUpdated,
|
||||
});
|
||||
|
||||
for (const [key, code] of getCommands()) {
|
||||
const consoleFront = await toolbox.target.getFront("console");
|
||||
const onNetwork = consoleFront.once("networkEvent", packet => {
|
||||
packets.set(key, getCleanedPacket(key, packet));
|
||||
});
|
||||
|
||||
const onNetworkUpdate = ui.once("network-message-updated", res => {
|
||||
const updateKey = `${key} update`;
|
||||
// We cannot ensure the form of the network update packet, some properties
|
||||
// might be in another order than in the original packet.
|
||||
// Hand-picking only what we need should prevent this.
|
||||
const packet = {
|
||||
networkInfo: {
|
||||
type: res.networkInfo.type,
|
||||
actor: res.networkInfo.actor,
|
||||
request: res.networkInfo.request,
|
||||
response: res.networkInfo.response,
|
||||
totalTime: res.networkInfo.totalTime,
|
||||
},
|
||||
const noExpectedUpdates = 7;
|
||||
const networkEventDone = new Promise(resolve => {
|
||||
addNetworkStub = ({ resourceType, targetFront, resource }) => {
|
||||
stubs.set(key, getCleanedPacket(key, getOrderedResource(resource)));
|
||||
resolve();
|
||||
};
|
||||
});
|
||||
const networkEventUpdateDone = new Promise(resolve => {
|
||||
let updateCount = 0;
|
||||
addNetworkUpdateStub = ({ resourceType, targetFront, resource }) => {
|
||||
const updateKey = `${key} update`;
|
||||
// make sure all the updates have been happened
|
||||
if (updateCount >= noExpectedUpdates) {
|
||||
stubs.set(
|
||||
updateKey,
|
||||
// We cannot ensure the form of the resource, some properties
|
||||
// might be in another order than in the original resource.
|
||||
// Hand-picking only what we need should prevent this.
|
||||
getCleanedPacket(updateKey, getOrderedResource(resource))
|
||||
);
|
||||
|
||||
resolve();
|
||||
} else {
|
||||
updateCount++;
|
||||
}
|
||||
};
|
||||
packets.set(updateKey, getCleanedPacket(updateKey, packet));
|
||||
});
|
||||
|
||||
await SpecialPowers.spawn(gBrowser.selectedBrowser, [code], function(
|
||||
|
@ -100,12 +122,42 @@ async function generateNetworkEventStubs() {
|
|||
content.wrappedJSObject.triggerPacket();
|
||||
script.remove();
|
||||
});
|
||||
|
||||
await Promise.all([onNetwork, onNetworkUpdate]);
|
||||
await Promise.all([networkEventDone, networkEventUpdateDone]);
|
||||
}
|
||||
|
||||
await closeTabAndToolbox();
|
||||
return packets;
|
||||
resourceWatcher.unwatchResources([resourceWatcher.TYPES.NETWORK_EVENT], {
|
||||
onAvailable,
|
||||
onUpdated,
|
||||
});
|
||||
return stubs;
|
||||
}
|
||||
// Ensures the order of the resource properties
|
||||
function getOrderedResource(resource) {
|
||||
return {
|
||||
resourceType: resource.resourceType,
|
||||
_type: resource._type,
|
||||
timeStamp: resource.timeStamp,
|
||||
node: resource.node,
|
||||
actor: resource.actor,
|
||||
discardRequestBody: resource.discardRequestBody,
|
||||
discardResponseBody: resource.discardResponseBody,
|
||||
startedDateTime: resource.startedDateTime,
|
||||
request: resource.request,
|
||||
isXHR: resource.isXHR,
|
||||
cause: resource.cause,
|
||||
response: resource.response,
|
||||
timings: resource.timings,
|
||||
private: resource.private,
|
||||
fromCache: resource.fromCache,
|
||||
fromServiceWorker: resource.fromServiceWorker,
|
||||
isThirdPartyTrackingResource: resource.isThirdPartyTrackingResource,
|
||||
referrerPolicy: resource.referrerPolicy,
|
||||
blockedReason: resource.blockedReason,
|
||||
channelId: resource.channelId,
|
||||
updates: resource.updates,
|
||||
updateType: resource.updateType,
|
||||
totalTime: resource.totalTime,
|
||||
securityState: resource.securityState,
|
||||
};
|
||||
}
|
||||
|
||||
function getCommands() {
|
||||
|
|
|
@ -209,8 +209,8 @@ function getCleanedPacket(key, packet) {
|
|||
|
||||
if (res.eventActor) {
|
||||
// Clean actor ids and startedDateTime on network messages.
|
||||
res.eventActor.actor = existingPacket.eventActor.actor;
|
||||
res.eventActor.startedDateTime = existingPacket.eventActor.startedDateTime;
|
||||
res.eventActor.actor = existingPacket.actor;
|
||||
res.eventActor.startedDateTime = existingPacket.startedDateTime;
|
||||
}
|
||||
|
||||
if (res.pageError) {
|
||||
|
@ -288,54 +288,37 @@ function getCleanedPacket(key, packet) {
|
|||
res.packet = Object.assign({}, res.packet, override);
|
||||
}
|
||||
|
||||
if (res.networkInfo) {
|
||||
if (res.networkInfo.startedDateTime) {
|
||||
res.networkInfo.startedDateTime =
|
||||
existingPacket.networkInfo.startedDateTime;
|
||||
}
|
||||
if (res.startedDateTime) {
|
||||
res.startedDateTime = existingPacket.startedDateTime;
|
||||
}
|
||||
|
||||
if (res.networkInfo.totalTime) {
|
||||
res.networkInfo.totalTime = existingPacket.networkInfo.totalTime;
|
||||
}
|
||||
if (res.totalTime && existingPacket.totalTime) {
|
||||
res.totalTime = existingPacket.totalTime;
|
||||
}
|
||||
|
||||
if (res.networkInfo.actor) {
|
||||
res.networkInfo.actor = existingPacket.networkInfo.actor;
|
||||
}
|
||||
if (res.actor && existingPacket.actor) {
|
||||
res.actor = existingPacket.actor;
|
||||
}
|
||||
|
||||
if (res.networkInfo.request && res.networkInfo.request.headersSize) {
|
||||
res.networkInfo.request.headersSize =
|
||||
existingPacket.networkInfo.request.headersSize;
|
||||
}
|
||||
if (res?.request?.headersSize && existingPacket?.request?.headersSize) {
|
||||
res.request.headersSize = existingPacket.request.headersSize;
|
||||
}
|
||||
|
||||
if (
|
||||
res.networkInfo.response &&
|
||||
res.networkInfo.response.headersSize !== undefined
|
||||
) {
|
||||
res.networkInfo.response.headersSize =
|
||||
existingPacket.networkInfo.response.headersSize;
|
||||
}
|
||||
if (
|
||||
res.networkInfo.response &&
|
||||
res.networkInfo.response.bodySize !== undefined
|
||||
) {
|
||||
res.networkInfo.response.bodySize =
|
||||
existingPacket.networkInfo.response.bodySize;
|
||||
}
|
||||
if (
|
||||
res.networkInfo.response &&
|
||||
res.networkInfo.response.transferredSize !== undefined
|
||||
) {
|
||||
res.networkInfo.response.transferredSize =
|
||||
existingPacket.networkInfo.response.transferredSize;
|
||||
}
|
||||
if (res?.response?.headersSize && existingPacket?.response?.headersSize) {
|
||||
res.response.headersSize = existingPacket.response.headersSize;
|
||||
}
|
||||
if (res?.response?.bodySize && existingPacket?.response?.bodySize) {
|
||||
res.response.bodySize = existingPacket.response.bodySize;
|
||||
}
|
||||
if (
|
||||
res?.response?.transferredSize &&
|
||||
existingPacket?.response?.transferredSize
|
||||
) {
|
||||
res.response.transferredSize = existingPacket.response.transferredSize;
|
||||
}
|
||||
|
||||
if (
|
||||
res.networkInfo.response &&
|
||||
res.networkInfo.response.waitingTime !== undefined
|
||||
) {
|
||||
res.networkInfo.response.waitingTime =
|
||||
existingPacket.networkInfo.response.waitingTime;
|
||||
}
|
||||
if (res?.response?.waitingTime && existingPacket?.response?.waitingTime) {
|
||||
res.response.waitingTime = existingPacket.response.waitingTime;
|
||||
}
|
||||
|
||||
if (res.updates && Array.isArray(res.updates)) {
|
||||
|
@ -348,7 +331,6 @@ function getCleanedPacket(key, packet) {
|
|||
existingPacket.helperResult.object
|
||||
);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -356,11 +338,12 @@ function cleanTimeStamp(packet) {
|
|||
// We want to have the same timestamp for every stub, so they won't be re-sorted when
|
||||
// adding them to the store.
|
||||
const uniqueTimeStamp = 1572867483805;
|
||||
|
||||
// lowercased timestamp
|
||||
if (packet.timestamp) {
|
||||
packet.timestamp = uniqueTimeStamp;
|
||||
}
|
||||
|
||||
// camelcased timestamp
|
||||
if (packet.timeStamp) {
|
||||
packet.timeStamp = uniqueTimeStamp;
|
||||
}
|
||||
|
@ -392,10 +375,6 @@ function cleanTimeStamp(packet) {
|
|||
if (packet?.pageError?.timeStamp) {
|
||||
packet.pageError.timeStamp = uniqueTimeStamp;
|
||||
}
|
||||
|
||||
if (packet?.networkInfo?.timeStamp) {
|
||||
packet.networkInfo.timeStamp = uniqueTimeStamp;
|
||||
}
|
||||
}
|
||||
|
||||
function copyExistingActor(a, b) {
|
||||
|
@ -462,9 +441,7 @@ const stubPackets = parsePacketsWithFronts(rawPackets);
|
|||
|
||||
const stubPreparedMessages = new Map();
|
||||
for (const [key, packet] of Array.from(stubPackets.entries())) {
|
||||
const transformedPacket = prepareMessage(${
|
||||
isNetworkMessage ? "packet.networkInfo || packet" : "packet"
|
||||
}, {
|
||||
const transformedPacket = prepareMessage(${"packet"}, {
|
||||
getNextId: () => "1",
|
||||
});
|
||||
const message = ${
|
||||
|
|
|
@ -68,8 +68,8 @@ describe("WebConsoleWrapper", () => {
|
|||
getPrivatePacket("XHR POST request")
|
||||
);
|
||||
|
||||
const postId = Symbol();
|
||||
const getId = Symbol();
|
||||
const postId = "pid1";
|
||||
const getId = "gid1";
|
||||
|
||||
// Add messages in the store to make sure that update to private requests are
|
||||
// removed from the queue.
|
||||
|
@ -94,11 +94,11 @@ describe("WebConsoleWrapper", () => {
|
|||
publicNetworkUpdate,
|
||||
{
|
||||
...getPrivatePacket("XHR GET request update"),
|
||||
networkInfo: { actor: getId },
|
||||
actor: getId,
|
||||
},
|
||||
{
|
||||
...getPrivatePacket("XHR POST request update"),
|
||||
networkInfo: { actor: postId },
|
||||
actor: postId,
|
||||
}
|
||||
);
|
||||
|
||||
|
|
|
@ -19,7 +19,8 @@ const {
|
|||
|
||||
const rawPackets = new Map();
|
||||
rawPackets.set(`GET request`, {
|
||||
"type": "networkEvent",
|
||||
"resourceType": "network-event",
|
||||
"_type": "NetworkEvent",
|
||||
"timeStamp": 1572867483805,
|
||||
"node": null,
|
||||
"actor": "server0.conn0.netEvent4",
|
||||
|
@ -29,20 +30,13 @@ rawPackets.set(`GET request`, {
|
|||
"request": {
|
||||
"url": "http://example.com/inexistent.html",
|
||||
"method": "GET",
|
||||
"headersSize": 396
|
||||
"headersSize": 385
|
||||
},
|
||||
"isXHR": false,
|
||||
"cause": {
|
||||
"type": "img",
|
||||
"loadingDocumentUri": "http://example.com/browser/devtools/client/webconsole/test/browser/stub-generators/test-network-event.html",
|
||||
"lastFrame": {
|
||||
"filename": "http://example.com/browser/devtools/client/webconsole/test/browser/stub-generators/test-network-event.html",
|
||||
"lineNumber": 3,
|
||||
"columnNumber": 1,
|
||||
"functionName": "triggerPacket",
|
||||
"asyncCause": null
|
||||
},
|
||||
"stacktraceAvailable": true
|
||||
"stacktraceAvailable": false
|
||||
},
|
||||
"response": {
|
||||
"httpVersion": "HTTP/1.1",
|
||||
|
@ -51,7 +45,6 @@ rawPackets.set(`GET request`, {
|
|||
"headersSize": 160,
|
||||
"remoteAddress": "127.0.0.1",
|
||||
"remotePort": 8888,
|
||||
"waitingTime": 2,
|
||||
"content": {
|
||||
"mimeType": "text/html; charset=utf-8"
|
||||
},
|
||||
|
@ -59,57 +52,84 @@ rawPackets.set(`GET request`, {
|
|||
"transferredSize": 578
|
||||
},
|
||||
"timings": {},
|
||||
"updates": [
|
||||
"requestHeaders",
|
||||
"requestCookies",
|
||||
"responseStart",
|
||||
"securityInfo",
|
||||
"responseHeaders",
|
||||
"responseCookies",
|
||||
"eventTimings",
|
||||
"responseContent"
|
||||
],
|
||||
"private": false,
|
||||
"isThirdPartyTrackingResource": false,
|
||||
"referrerPolicy": "no-referrer-when-downgrade",
|
||||
"channelId": 265845590720515
|
||||
"channelId": 265845590720515,
|
||||
"updates": [
|
||||
"eventTimings",
|
||||
"requestCookies",
|
||||
"requestHeaders",
|
||||
"responseContent",
|
||||
"responseCookies",
|
||||
"responseHeaders",
|
||||
"responseStart",
|
||||
"securityInfo"
|
||||
]
|
||||
});
|
||||
|
||||
rawPackets.set(`GET request update`, {
|
||||
"networkInfo": {
|
||||
"type": "networkEvent",
|
||||
"actor": "server0.conn0.netEvent4",
|
||||
"request": {
|
||||
"url": "http://example.com/inexistent.html",
|
||||
"method": "GET",
|
||||
"headersSize": 396
|
||||
"resourceType": "network-event",
|
||||
"_type": "NetworkEvent",
|
||||
"timeStamp": 1572867483805,
|
||||
"node": null,
|
||||
"actor": "server0.conn0.netEvent5",
|
||||
"discardRequestBody": true,
|
||||
"discardResponseBody": false,
|
||||
"startedDateTime": "2020-07-07T14:41:14.572Z",
|
||||
"request": {
|
||||
"url": "http://example.com/inexistent.html",
|
||||
"method": "GET",
|
||||
"headersSize": 385
|
||||
},
|
||||
"isXHR": false,
|
||||
"cause": {
|
||||
"type": "img",
|
||||
"loadingDocumentUri": "http://example.com/browser/devtools/client/webconsole/test/browser/stub-generators/test-network-event.html",
|
||||
"stacktraceAvailable": false
|
||||
},
|
||||
"response": {
|
||||
"httpVersion": "HTTP/1.1",
|
||||
"status": "404",
|
||||
"statusText": "Not Found",
|
||||
"headersSize": 160,
|
||||
"remoteAddress": "127.0.0.1",
|
||||
"remotePort": 8888,
|
||||
"content": {
|
||||
"mimeType": "text/html; charset=utf-8"
|
||||
},
|
||||
"response": {
|
||||
"httpVersion": "HTTP/1.1",
|
||||
"status": "404",
|
||||
"statusText": "Not Found",
|
||||
"headersSize": 160,
|
||||
"remoteAddress": "127.0.0.1",
|
||||
"remotePort": 8888,
|
||||
"waitingTime": 2,
|
||||
"content": {
|
||||
"mimeType": "text/html; charset=utf-8"
|
||||
},
|
||||
"bodySize": 418,
|
||||
"transferredSize": 578
|
||||
},
|
||||
"totalTime": 14
|
||||
}
|
||||
"bodySize": 418,
|
||||
"transferredSize": 578
|
||||
},
|
||||
"timings": {},
|
||||
"private": false,
|
||||
"isThirdPartyTrackingResource": false,
|
||||
"referrerPolicy": "no-referrer-when-downgrade",
|
||||
"channelId": 202499118071811,
|
||||
"updates": [
|
||||
"eventTimings",
|
||||
"requestCookies",
|
||||
"requestHeaders",
|
||||
"responseContent",
|
||||
"responseCookies",
|
||||
"responseHeaders",
|
||||
"responseStart",
|
||||
"securityInfo"
|
||||
],
|
||||
"updateType": "responseContent",
|
||||
"totalTime": 3,
|
||||
"securityState": "insecure"
|
||||
});
|
||||
|
||||
rawPackets.set(`XHR GET request`, {
|
||||
"type": "networkEvent",
|
||||
"resourceType": "network-event",
|
||||
"_type": "NetworkEvent",
|
||||
"timeStamp": 1572867483805,
|
||||
"node": null,
|
||||
"actor": "server0.conn0.netEvent20",
|
||||
"actor": "server0.conn0.netEvent21",
|
||||
"discardRequestBody": true,
|
||||
"discardResponseBody": true,
|
||||
"startedDateTime": "2019-11-04T11:06:34.909Z",
|
||||
"startedDateTime": "2020-07-07T14:41:14.612Z",
|
||||
"request": {
|
||||
"url": "http://example.com/inexistent.html",
|
||||
"method": "GET",
|
||||
|
@ -135,7 +155,6 @@ rawPackets.set(`XHR GET request`, {
|
|||
"headersSize": 160,
|
||||
"remoteAddress": "127.0.0.1",
|
||||
"remotePort": 8888,
|
||||
"waitingTime": 1,
|
||||
"content": {
|
||||
"mimeType": "text/html; charset=utf-8"
|
||||
},
|
||||
|
@ -143,61 +162,34 @@ rawPackets.set(`XHR GET request`, {
|
|||
"transferredSize": 578
|
||||
},
|
||||
"timings": {},
|
||||
"updates": [
|
||||
"requestHeaders",
|
||||
"requestCookies",
|
||||
"responseStart",
|
||||
"securityInfo",
|
||||
"responseHeaders",
|
||||
"responseCookies",
|
||||
"eventTimings",
|
||||
"responseContent"
|
||||
],
|
||||
"private": false,
|
||||
"isThirdPartyTrackingResource": false,
|
||||
"referrerPolicy": "no-referrer-when-downgrade",
|
||||
"channelId": 265845590720516
|
||||
"channelId": 202499118071812,
|
||||
"updates": [
|
||||
"eventTimings",
|
||||
"requestCookies",
|
||||
"requestHeaders",
|
||||
"responseContent",
|
||||
"responseCookies",
|
||||
"responseHeaders",
|
||||
"responseStart",
|
||||
"securityInfo"
|
||||
]
|
||||
});
|
||||
|
||||
rawPackets.set(`XHR GET request update`, {
|
||||
"networkInfo": {
|
||||
"type": "networkEvent",
|
||||
"actor": "server0.conn0.netEvent20",
|
||||
"request": {
|
||||
"url": "http://example.com/inexistent.html",
|
||||
"method": "GET",
|
||||
"headersSize": 385
|
||||
},
|
||||
"response": {
|
||||
"httpVersion": "HTTP/1.1",
|
||||
"status": "404",
|
||||
"statusText": "Not Found",
|
||||
"headersSize": 160,
|
||||
"remoteAddress": "127.0.0.1",
|
||||
"remotePort": 8888,
|
||||
"waitingTime": 1,
|
||||
"content": {
|
||||
"mimeType": "text/html; charset=utf-8"
|
||||
},
|
||||
"bodySize": 418,
|
||||
"transferredSize": 578
|
||||
},
|
||||
"totalTime": 0
|
||||
}
|
||||
});
|
||||
|
||||
rawPackets.set(`XHR POST request`, {
|
||||
"type": "networkEvent",
|
||||
"resourceType": "network-event",
|
||||
"_type": "NetworkEvent",
|
||||
"timeStamp": 1572867483805,
|
||||
"node": null,
|
||||
"actor": "server0.conn0.netEvent36",
|
||||
"actor": "server0.conn0.netEvent20",
|
||||
"discardRequestBody": true,
|
||||
"discardResponseBody": true,
|
||||
"startedDateTime": "2019-11-04T11:06:35.007Z",
|
||||
"discardResponseBody": false,
|
||||
"request": {
|
||||
"url": "http://example.com/inexistent.html",
|
||||
"method": "POST",
|
||||
"headersSize": 433
|
||||
"method": "GET",
|
||||
"headersSize": 385
|
||||
},
|
||||
"isXHR": true,
|
||||
"cause": {
|
||||
|
@ -219,7 +211,6 @@ rawPackets.set(`XHR POST request`, {
|
|||
"headersSize": 160,
|
||||
"remoteAddress": "127.0.0.1",
|
||||
"remotePort": 8888,
|
||||
"waitingTime": 1,
|
||||
"content": {
|
||||
"mimeType": "text/html; charset=utf-8"
|
||||
},
|
||||
|
@ -227,47 +218,137 @@ rawPackets.set(`XHR POST request`, {
|
|||
"transferredSize": 578
|
||||
},
|
||||
"timings": {},
|
||||
"updates": [
|
||||
"requestHeaders",
|
||||
"requestCookies",
|
||||
"responseStart",
|
||||
"securityInfo",
|
||||
"responseHeaders",
|
||||
"responseCookies",
|
||||
"eventTimings",
|
||||
"responseContent"
|
||||
],
|
||||
"private": false,
|
||||
"isThirdPartyTrackingResource": false,
|
||||
"referrerPolicy": "no-referrer-when-downgrade",
|
||||
"channelId": 265845590720517
|
||||
"updates": [
|
||||
"eventTimings",
|
||||
"requestCookies",
|
||||
"requestHeaders",
|
||||
"responseContent",
|
||||
"responseCookies",
|
||||
"responseHeaders",
|
||||
"responseStart",
|
||||
"securityInfo"
|
||||
],
|
||||
"updateType": "responseContent",
|
||||
"totalTime": 1,
|
||||
"securityState": "insecure"
|
||||
});
|
||||
|
||||
rawPackets.set(`XHR POST request`, {
|
||||
"resourceType": "network-event",
|
||||
"_type": "NetworkEvent",
|
||||
"timeStamp": 1572867483805,
|
||||
"node": null,
|
||||
"actor": "server0.conn0.netEvent36",
|
||||
"discardRequestBody": true,
|
||||
"discardResponseBody": true,
|
||||
"startedDateTime": "2019-11-04T11:06:35.007Z",
|
||||
"request": {
|
||||
"url": "http://example.com/inexistent.html",
|
||||
"method": "POST",
|
||||
"headersSize": 385
|
||||
},
|
||||
"isXHR": true,
|
||||
"cause": {
|
||||
"type": "xhr",
|
||||
"loadingDocumentUri": "http://example.com/browser/devtools/client/webconsole/test/browser/stub-generators/test-network-event.html",
|
||||
"lastFrame": {
|
||||
"filename": "http://example.com/browser/devtools/client/webconsole/test/browser/stub-generators/test-network-event.html",
|
||||
"lineNumber": 4,
|
||||
"columnNumber": 5,
|
||||
"functionName": "triggerPacket",
|
||||
"asyncCause": null
|
||||
},
|
||||
"stacktraceAvailable": true
|
||||
},
|
||||
"response": {
|
||||
"httpVersion": "HTTP/1.1",
|
||||
"status": "404",
|
||||
"statusText": "Not Found",
|
||||
"headersSize": 160,
|
||||
"remoteAddress": "127.0.0.1",
|
||||
"remotePort": 8888,
|
||||
"content": {
|
||||
"mimeType": "text/html; charset=utf-8"
|
||||
},
|
||||
"bodySize": 418,
|
||||
"transferredSize": 578
|
||||
},
|
||||
"timings": {},
|
||||
"private": false,
|
||||
"isThirdPartyTrackingResource": false,
|
||||
"referrerPolicy": "no-referrer-when-downgrade",
|
||||
"channelId": 265845590720517,
|
||||
"updates": [
|
||||
"eventTimings",
|
||||
"requestCookies",
|
||||
"requestHeaders",
|
||||
"responseContent",
|
||||
"responseCookies",
|
||||
"responseHeaders",
|
||||
"responseStart",
|
||||
"securityInfo"
|
||||
]
|
||||
});
|
||||
|
||||
rawPackets.set(`XHR POST request update`, {
|
||||
"networkInfo": {
|
||||
"type": "networkEvent",
|
||||
"actor": "server0.conn0.netEvent36",
|
||||
"request": {
|
||||
"url": "http://example.com/inexistent.html",
|
||||
"method": "POST",
|
||||
"headersSize": 433
|
||||
"resourceType": "network-event",
|
||||
"_type": "NetworkEvent",
|
||||
"timeStamp": 1572867483805,
|
||||
"node": null,
|
||||
"actor": "server0.conn0.netEvent36",
|
||||
"discardRequestBody": true,
|
||||
"discardResponseBody": false,
|
||||
"request": {
|
||||
"url": "http://example.com/inexistent.html",
|
||||
"method": "POST",
|
||||
"headersSize": 385
|
||||
},
|
||||
"isXHR": true,
|
||||
"cause": {
|
||||
"type": "xhr",
|
||||
"loadingDocumentUri": "http://example.com/browser/devtools/client/webconsole/test/browser/stub-generators/test-network-event.html",
|
||||
"lastFrame": {
|
||||
"filename": "http://example.com/browser/devtools/client/webconsole/test/browser/stub-generators/test-network-event.html",
|
||||
"lineNumber": 4,
|
||||
"columnNumber": 5,
|
||||
"functionName": "triggerPacket",
|
||||
"asyncCause": null
|
||||
},
|
||||
"response": {
|
||||
"httpVersion": "HTTP/1.1",
|
||||
"status": "404",
|
||||
"statusText": "Not Found",
|
||||
"headersSize": 160,
|
||||
"remoteAddress": "127.0.0.1",
|
||||
"remotePort": 8888,
|
||||
"waitingTime": 1,
|
||||
"content": {
|
||||
"mimeType": "text/html; charset=utf-8"
|
||||
},
|
||||
"bodySize": 418,
|
||||
"transferredSize": 578
|
||||
"stacktraceAvailable": true
|
||||
},
|
||||
"response": {
|
||||
"httpVersion": "HTTP/1.1",
|
||||
"status": "404",
|
||||
"statusText": "Not Found",
|
||||
"headersSize": 160,
|
||||
"remoteAddress": "127.0.0.1",
|
||||
"remotePort": 8888,
|
||||
"content": {
|
||||
"mimeType": "text/html; charset=utf-8"
|
||||
},
|
||||
"totalTime": 0
|
||||
}
|
||||
"bodySize": 418,
|
||||
"transferredSize": 578
|
||||
},
|
||||
"timings": {},
|
||||
"private": false,
|
||||
"isThirdPartyTrackingResource": false,
|
||||
"referrerPolicy": "no-referrer-when-downgrade",
|
||||
"updates": [
|
||||
"eventTimings",
|
||||
"requestCookies",
|
||||
"requestHeaders",
|
||||
"responseContent",
|
||||
"responseCookies",
|
||||
"responseHeaders",
|
||||
"responseStart",
|
||||
"securityInfo"
|
||||
],
|
||||
"updateType": "responseContent",
|
||||
"totalTime": 2,
|
||||
"securityState": "insecure"
|
||||
});
|
||||
|
||||
|
||||
|
@ -275,7 +356,7 @@ const stubPackets = parsePacketsWithFronts(rawPackets);
|
|||
|
||||
const stubPreparedMessages = new Map();
|
||||
for (const [key, packet] of Array.from(stubPackets.entries())) {
|
||||
const transformedPacket = prepareMessage(packet.networkInfo || packet, {
|
||||
const transformedPacket = prepareMessage(packet, {
|
||||
getNextId: () => "1",
|
||||
});
|
||||
const message = NetworkEventMessage(transformedPacket);
|
||||
|
|
|
@ -881,15 +881,9 @@ describe("Message reducer:", () => {
|
|||
let updatePacket = clonePacket(stubPackets.get("GET request update"));
|
||||
|
||||
packet.actor = "message1";
|
||||
updatePacket.networkInfo.actor = "message1";
|
||||
updatePacket.actor = "message1";
|
||||
dispatch(actions.messagesAdd([packet]));
|
||||
dispatch(
|
||||
actions.networkMessageUpdate(
|
||||
updatePacket.networkInfo,
|
||||
null,
|
||||
updatePacket
|
||||
)
|
||||
);
|
||||
dispatch(actions.networkMessageUpdate(updatePacket, null));
|
||||
|
||||
let networkUpdates = getAllNetworkMessagesUpdateById(getState());
|
||||
expect(Object.keys(networkUpdates)).toEqual(["message1"]);
|
||||
|
@ -897,15 +891,9 @@ describe("Message reducer:", () => {
|
|||
packet = clonePacket(stubPackets.get("GET request"));
|
||||
updatePacket = stubPackets.get("XHR GET request update");
|
||||
packet.actor = "message2";
|
||||
updatePacket.networkInfo.actor = "message2";
|
||||
updatePacket.actor = "message2";
|
||||
dispatch(actions.messagesAdd([packet]));
|
||||
dispatch(
|
||||
actions.networkMessageUpdate(
|
||||
updatePacket.networkInfo,
|
||||
null,
|
||||
updatePacket
|
||||
)
|
||||
);
|
||||
dispatch(actions.networkMessageUpdate(updatePacket, null));
|
||||
|
||||
networkUpdates = getAllNetworkMessagesUpdateById(getState());
|
||||
expect(Object.keys(networkUpdates)).toEqual(["message1", "message2"]);
|
||||
|
@ -915,13 +903,7 @@ describe("Message reducer:", () => {
|
|||
const { dispatch, getState } = setupStore(["XHR GET request"]);
|
||||
|
||||
const updatePacket = stubPackets.get("XHR GET request update");
|
||||
dispatch(
|
||||
actions.networkMessageUpdate(
|
||||
updatePacket.networkInfo,
|
||||
null,
|
||||
updatePacket
|
||||
)
|
||||
);
|
||||
dispatch(actions.networkMessageUpdate(updatePacket, null));
|
||||
|
||||
let networkUpdates = getAllNetworkMessagesUpdateById(getState());
|
||||
expect(Object.keys(networkUpdates).length > 0).toBe(true);
|
||||
|
@ -945,37 +927,19 @@ describe("Message reducer:", () => {
|
|||
stubPackets.get("XHR GET request update")
|
||||
);
|
||||
packet.actor = "message1";
|
||||
updatePacket.networkInfo.actor = "message1";
|
||||
updatePacket.actor = "message1";
|
||||
dispatch(actions.messagesAdd([packet]));
|
||||
dispatch(
|
||||
actions.networkMessageUpdate(
|
||||
updatePacket.networkInfo,
|
||||
null,
|
||||
updatePacket
|
||||
)
|
||||
);
|
||||
dispatch(actions.networkMessageUpdate(updatePacket, null));
|
||||
|
||||
packet.actor = "message2";
|
||||
updatePacket.networkInfo.actor = "message2";
|
||||
updatePacket.actor = "message2";
|
||||
dispatch(actions.messagesAdd([packet]));
|
||||
dispatch(
|
||||
actions.networkMessageUpdate(
|
||||
updatePacket.networkInfo,
|
||||
null,
|
||||
updatePacket
|
||||
)
|
||||
);
|
||||
dispatch(actions.networkMessageUpdate(updatePacket, null));
|
||||
|
||||
packet.actor = "message3";
|
||||
updatePacket.networkInfo.actor = "message3";
|
||||
updatePacket.actor = "message3";
|
||||
dispatch(actions.messagesAdd([packet]));
|
||||
dispatch(
|
||||
actions.networkMessageUpdate(
|
||||
updatePacket.networkInfo,
|
||||
null,
|
||||
updatePacket
|
||||
)
|
||||
);
|
||||
dispatch(actions.networkMessageUpdate(updatePacket, null));
|
||||
|
||||
// Check that we have the expected data.
|
||||
const messages = getAllMessagesById(getState());
|
||||
|
|
|
@ -35,11 +35,9 @@ describe("Network message reducer:", () => {
|
|||
const updatePacket = clonePacket(stubPackets.get("GET request update"));
|
||||
|
||||
packet.actor = "message1";
|
||||
updatePacket.networkInfo.actor = "message1";
|
||||
updatePacket.actor = "message1";
|
||||
dispatch(actions.messagesAdd([packet]));
|
||||
dispatch(
|
||||
actions.networkMessageUpdate(updatePacket.networkInfo, null, updatePacket)
|
||||
);
|
||||
dispatch(actions.networkMessageUpdate(updatePacket, null));
|
||||
});
|
||||
|
||||
describe("networkMessagesUpdateById", () => {
|
||||
|
|
|
@ -115,7 +115,7 @@ function transformResource(resource) {
|
|||
return transformCSSMessageResource(resource);
|
||||
}
|
||||
|
||||
case "networkEvent": {
|
||||
case ResourceWatcher.TYPES.NETWORK_EVENT: {
|
||||
return transformNetworkEventResource(resource);
|
||||
}
|
||||
|
||||
|
|
|
@ -34,11 +34,8 @@ class WebConsoleConnectionProxy {
|
|||
this.webConsoleUI = webConsoleUI;
|
||||
this.target = target;
|
||||
this.needContentProcessMessagesListener = needContentProcessMessagesListener;
|
||||
|
||||
this._connecter = null;
|
||||
|
||||
this._onNetworkEvent = this._onNetworkEvent.bind(this);
|
||||
this._onNetworkEventUpdate = this._onNetworkEventUpdate.bind(this);
|
||||
this._onTabNavigated = this._onTabNavigated.bind(this);
|
||||
this._onTabWillNavigate = this._onTabWillNavigate.bind(this);
|
||||
this._onLastPrivateContextExited = this._onLastPrivateContextExited.bind(
|
||||
|
@ -81,9 +78,6 @@ class WebConsoleConnectionProxy {
|
|||
);
|
||||
await this.webConsoleUI.setSaveRequestAndResponseBodies(saveBodies);
|
||||
|
||||
const networkMessages = this._getNetworkMessages();
|
||||
this.dispatchMessagesAdd(networkMessages);
|
||||
|
||||
this._addWebConsoleFrontEventListeners();
|
||||
|
||||
if (this.webConsoleFront && !this.webConsoleFront.hasNativeConsoleAPI) {
|
||||
|
@ -122,19 +116,15 @@ class WebConsoleConnectionProxy {
|
|||
* @returns Promise
|
||||
*/
|
||||
_attachConsole() {
|
||||
if (!this.webConsoleFront) {
|
||||
if (!this.webConsoleFront || !this.needContentProcessMessagesListener) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const listeners = ["NetworkActivity"];
|
||||
// Enable the forwarding of console messages to the parent process
|
||||
// when we open the Browser Console or Toolbox without fission support. If Fission
|
||||
// is enabled, we don't use the ContentProcessMessages listener, but attach to the
|
||||
// content processes directly.
|
||||
if (this.needContentProcessMessagesListener) {
|
||||
listeners.push("ContentProcessMessages");
|
||||
}
|
||||
return this.webConsoleFront.startListeners(listeners);
|
||||
return this.webConsoleFront.startListeners(["ContentProcessMessages"]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -147,8 +137,6 @@ class WebConsoleConnectionProxy {
|
|||
return;
|
||||
}
|
||||
|
||||
this.webConsoleFront.on("networkEvent", this._onNetworkEvent);
|
||||
this.webConsoleFront.on("networkEventUpdate", this._onNetworkEventUpdate);
|
||||
this.webConsoleFront.on(
|
||||
"lastPrivateContextExited",
|
||||
this._onLastPrivateContextExited
|
||||
|
@ -165,8 +153,6 @@ class WebConsoleConnectionProxy {
|
|||
* @private
|
||||
*/
|
||||
_removeWebConsoleFrontEventListeners() {
|
||||
this.webConsoleFront.off("networkEvent", this._onNetworkEvent);
|
||||
this.webConsoleFront.off("networkEventUpdate", this._onNetworkEventUpdate);
|
||||
this.webConsoleFront.off(
|
||||
"lastPrivateContextExited",
|
||||
this._onLastPrivateContextExited
|
||||
|
@ -177,51 +163,11 @@ class WebConsoleConnectionProxy {
|
|||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get network messages from the server.
|
||||
*
|
||||
* @private
|
||||
* @returns An array of network messages.
|
||||
*/
|
||||
_getNetworkMessages() {
|
||||
if (!this.webConsoleFront) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return Array.from(this.webConsoleFront.getNetworkEvents());
|
||||
}
|
||||
|
||||
_clearLogpointMessages(logpointId) {
|
||||
// Some message might try to update while we are closing the toolbox.
|
||||
if (!this.webConsoleUI?.wrapper) {
|
||||
return;
|
||||
if (this.webConsoleUI?.wrapper) {
|
||||
this.webConsoleUI.wrapper.dispatchClearLogpointMessages(logpointId);
|
||||
}
|
||||
|
||||
this.webConsoleUI.wrapper.dispatchClearLogpointMessages(logpointId);
|
||||
}
|
||||
|
||||
/**
|
||||
* The "networkEvent" message type handler. We redirect any message to
|
||||
* the UI for displaying.
|
||||
*
|
||||
* @private
|
||||
* @param object networkInfo
|
||||
* The network request information.
|
||||
*/
|
||||
_onNetworkEvent(networkInfo) {
|
||||
this.dispatchMessageAdd(networkInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* The "networkEventUpdate" message type handler. We redirect any message to
|
||||
* the UI for displaying.
|
||||
*
|
||||
* @private
|
||||
* @param object response
|
||||
* The update response received from the server.
|
||||
*/
|
||||
_onNetworkEventUpdate(response) {
|
||||
this.dispatchMessageUpdate(response.networkInfo, response);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -270,39 +216,6 @@ class WebConsoleConnectionProxy {
|
|||
this.webConsoleUI.handleTabWillNavigate(packet);
|
||||
}
|
||||
|
||||
/**
|
||||
* Dispatch a message add on the new frontend and emit an event for tests.
|
||||
*/
|
||||
dispatchMessageAdd(packet) {
|
||||
// Some message might try to update while we are closing the toolbox.
|
||||
if (!this.webConsoleUI?.wrapper) {
|
||||
return;
|
||||
}
|
||||
this.webConsoleUI.wrapper.dispatchMessageAdd(packet);
|
||||
}
|
||||
|
||||
/**
|
||||
* Batched dispatch of messages.
|
||||
*/
|
||||
dispatchMessagesAdd(packets) {
|
||||
// Some message might try to update while we are closing the toolbox.
|
||||
if (!this.webConsoleUI?.wrapper) {
|
||||
return;
|
||||
}
|
||||
this.webConsoleUI.wrapper.dispatchMessagesAdd(packets);
|
||||
}
|
||||
|
||||
/**
|
||||
* Dispatch a message event on the new frontend and emit an event for tests.
|
||||
*/
|
||||
dispatchMessageUpdate(networkInfo, response) {
|
||||
// Some message might try to update while we are closing the toolbox.
|
||||
if (!this.webConsoleUI?.wrapper) {
|
||||
return;
|
||||
}
|
||||
this.webConsoleUI.wrapper.dispatchMessageUpdate(networkInfo, response);
|
||||
}
|
||||
|
||||
/**
|
||||
* Disconnect the Web Console from the remote server.
|
||||
*
|
||||
|
|
|
@ -79,6 +79,7 @@ class WebConsoleUI {
|
|||
this._onTargetAvailable = this._onTargetAvailable.bind(this);
|
||||
this._onTargetDestroyed = this._onTargetDestroyed.bind(this);
|
||||
this._onResourceAvailable = this._onResourceAvailable.bind(this);
|
||||
this._onResourceUpdated = this._onResourceUpdated.bind(this);
|
||||
|
||||
EventEmitter.decorate(this);
|
||||
}
|
||||
|
@ -235,19 +236,13 @@ class WebConsoleUI {
|
|||
if (this.wrapper) {
|
||||
this.wrapper.dispatchMessagesClear();
|
||||
}
|
||||
this.clearNetworkRequests();
|
||||
|
||||
if (clearStorage) {
|
||||
this.clearMessagesCache();
|
||||
}
|
||||
this.emitForTests("messages-cleared");
|
||||
}
|
||||
|
||||
clearNetworkRequests() {
|
||||
for (const proxy of this.getAllProxies()) {
|
||||
proxy.webConsoleFront.clearNetworkRequests();
|
||||
}
|
||||
}
|
||||
|
||||
clearMessagesCache() {
|
||||
for (const proxy of this.getAllProxies()) {
|
||||
proxy.webConsoleFront.clearMessagesCache();
|
||||
|
@ -342,8 +337,12 @@ class WebConsoleUI {
|
|||
resourceWatcher.TYPES.CONSOLE_MESSAGE,
|
||||
resourceWatcher.TYPES.ERROR_MESSAGE,
|
||||
resourceWatcher.TYPES.PLATFORM_MESSAGE,
|
||||
resourceWatcher.TYPES.NETWORK_EVENT,
|
||||
],
|
||||
{ onAvailable: this._onResourceAvailable }
|
||||
{
|
||||
onAvailable: this._onResourceAvailable,
|
||||
onUpdated: this._onResourceUpdated,
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -370,6 +369,12 @@ class WebConsoleUI {
|
|||
this.wrapper.dispatchMessageAdd(resource);
|
||||
}
|
||||
|
||||
_onResourceUpdated({ resourceType, targetFront, resource }) {
|
||||
if (resourceType == this.hud.resourceWatcher.TYPES.NETWORK_EVENT) {
|
||||
this.wrapper.dispatchMessageUpdate(resource);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called any time a new target is available.
|
||||
* i.e. it was already existing or has just been created.
|
||||
|
|
|
@ -168,9 +168,7 @@ class WebConsoleWrapper {
|
|||
// since we can receive updates even if the message isn't rendered yet.
|
||||
const messages = [...getAllMessagesById(store.getState()).values()];
|
||||
this.queuedMessageUpdates = this.queuedMessageUpdates.filter(
|
||||
({ networkInfo }) => {
|
||||
const { actor } = networkInfo;
|
||||
|
||||
({ actor }) => {
|
||||
const queuedNetworkMessage = this.queuedMessageAdds.find(
|
||||
p => p.actor === actor
|
||||
);
|
||||
|
@ -210,24 +208,24 @@ class WebConsoleWrapper {
|
|||
store.dispatch(actions.privateMessagesClear());
|
||||
}
|
||||
|
||||
dispatchMessageUpdate(message, res) {
|
||||
dispatchMessageUpdate(message) {
|
||||
// network-message-updated will emit when all the update message arrives.
|
||||
// Since we can't ensure the order of the network update, we check
|
||||
// that networkInfo.updates has all we need.
|
||||
// that message.updates has all we need.
|
||||
// Note that 'requestPostData' is sent only for POST requests, so we need
|
||||
// to count with that.
|
||||
const NUMBER_OF_NETWORK_UPDATE = 8;
|
||||
|
||||
let expectedLength = NUMBER_OF_NETWORK_UPDATE;
|
||||
if (res.networkInfo.updates.includes("responseCache")) {
|
||||
if (message.updates.includes("responseCache")) {
|
||||
expectedLength++;
|
||||
}
|
||||
if (res.networkInfo.updates.includes("requestPostData")) {
|
||||
if (message.updates.includes("requestPostData")) {
|
||||
expectedLength++;
|
||||
}
|
||||
|
||||
if (res.networkInfo.updates.length === expectedLength) {
|
||||
this.batchedMessageUpdates({ res, message });
|
||||
if (message.updates.length === expectedLength) {
|
||||
this.batchedMessageUpdates(message);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -257,7 +255,6 @@ class WebConsoleWrapper {
|
|||
packet.timeStamp = Date.now();
|
||||
this.dispatchMessageAdd(packet);
|
||||
} else {
|
||||
this.webConsoleUI.clearNetworkRequests();
|
||||
this.dispatchMessagesClear();
|
||||
store.dispatch({
|
||||
type: Constants.WILL_NAVIGATE,
|
||||
|
@ -265,8 +262,8 @@ class WebConsoleWrapper {
|
|||
}
|
||||
}
|
||||
|
||||
batchedMessageUpdates(info) {
|
||||
this.queuedMessageUpdates.push(info);
|
||||
batchedMessageUpdates(message) {
|
||||
this.queuedMessageUpdates.push(message);
|
||||
this.setTimeoutIfNeeded();
|
||||
}
|
||||
|
||||
|
@ -345,11 +342,9 @@ class WebConsoleWrapper {
|
|||
this.queuedMessageAdds = [];
|
||||
|
||||
if (this.queuedMessageUpdates.length > 0) {
|
||||
for (const { message, res } of this.queuedMessageUpdates) {
|
||||
await store.dispatch(
|
||||
actions.networkMessageUpdate(message, null, res)
|
||||
);
|
||||
this.webConsoleUI.emitForTests("network-message-updated", res);
|
||||
for (const message of this.queuedMessageUpdates) {
|
||||
await store.dispatch(actions.networkMessageUpdate(message, null));
|
||||
this.webConsoleUI.emitForTests("network-message-updated", message);
|
||||
}
|
||||
this.queuedMessageUpdates = [];
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ DevToolsModules(
|
|||
'css-changes.js',
|
||||
'css-messages.js',
|
||||
'error-messages.js',
|
||||
'network-events.js',
|
||||
'platform-messages.js',
|
||||
'root-node.js',
|
||||
'stylesheet.js',
|
||||
|
|
|
@ -0,0 +1,142 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
const {
|
||||
ResourceWatcher,
|
||||
} = require("devtools/shared/resources/resource-watcher");
|
||||
|
||||
module.exports = async function({
|
||||
targetList,
|
||||
targetFront,
|
||||
isFissionEnabledOnContentToolbox,
|
||||
onAvailable,
|
||||
onUpdated,
|
||||
}) {
|
||||
// Allow the top level target unconditionnally.
|
||||
// Also allow frame, but only in content toolbox, when the fission/content toolbox pref is
|
||||
// set. i.e. still ignore them in the content of the browser toolbox as we inspect
|
||||
// messages via the process targets
|
||||
// Also ignore workers as they are not supported yet. (see bug 1592584)
|
||||
const isContentToolbox = targetList.targetFront.isLocalTab;
|
||||
const listenForFrames = isContentToolbox && isFissionEnabledOnContentToolbox;
|
||||
const isAllowed =
|
||||
targetFront.isTopLevel ||
|
||||
targetFront.targetType === targetList.TYPES.PROCESS ||
|
||||
(targetFront.targetType === targetList.TYPES.FRAME && listenForFrames);
|
||||
|
||||
if (!isAllowed) {
|
||||
return;
|
||||
}
|
||||
|
||||
const webConsoleFront = await targetFront.getFront("console");
|
||||
const _resources = new Map();
|
||||
|
||||
function onNetworkEvent(packet) {
|
||||
const actor = packet.eventActor;
|
||||
const resource = {
|
||||
resourceType: ResourceWatcher.TYPES.NETWORK_EVENT,
|
||||
_type: "NetworkEvent",
|
||||
timeStamp: actor.timeStamp,
|
||||
node: null,
|
||||
actor: actor.actor,
|
||||
discardRequestBody: true,
|
||||
discardResponseBody: true,
|
||||
startedDateTime: actor.startedDateTime,
|
||||
request: {
|
||||
url: actor.url,
|
||||
method: actor.method,
|
||||
},
|
||||
isXHR: actor.isXHR,
|
||||
cause: actor.cause,
|
||||
response: {},
|
||||
timings: {},
|
||||
private: actor.private,
|
||||
fromCache: actor.fromCache,
|
||||
fromServiceWorker: actor.fromServiceWorker,
|
||||
isThirdPartyTrackingResource: actor.isThirdPartyTrackingResource,
|
||||
referrerPolicy: actor.referrerPolicy,
|
||||
blockedReason: actor.blockedReason,
|
||||
channelId: actor.channelId,
|
||||
updates: [],
|
||||
};
|
||||
_resources.set(actor.actor, resource);
|
||||
onAvailable([resource]);
|
||||
}
|
||||
|
||||
function onNetworkEventUpdate(packet) {
|
||||
const resource = _resources.get(packet.from);
|
||||
|
||||
if (!resource) {
|
||||
return;
|
||||
}
|
||||
|
||||
resource.updates.push(packet.updateType);
|
||||
resource.updateType = packet.updateType;
|
||||
|
||||
switch (packet.updateType) {
|
||||
case "requestHeaders":
|
||||
resource.request.headersSize = packet.headersSize;
|
||||
break;
|
||||
case "requestPostData":
|
||||
resource.discardRequestBody = packet.discardRequestBody;
|
||||
resource.request.bodySize = packet.dataSize;
|
||||
break;
|
||||
case "responseStart":
|
||||
resource.response.httpVersion = packet.response.httpVersion;
|
||||
resource.response.status = packet.response.status;
|
||||
resource.response.statusText = packet.response.statusText;
|
||||
resource.response.headersSize = packet.response.headersSize;
|
||||
resource.response.remoteAddress = packet.response.remoteAddress;
|
||||
resource.response.remotePort = packet.response.remotePort;
|
||||
resource.discardResponseBody = packet.response.discardResponseBody;
|
||||
resource.response.content = {
|
||||
mimeType: packet.response.mimeType,
|
||||
};
|
||||
break;
|
||||
case "responseContent":
|
||||
resource.response.content = {
|
||||
mimeType: packet.mimeType,
|
||||
};
|
||||
resource.response.bodySize = packet.contentSize;
|
||||
resource.response.transferredSize = packet.transferredSize;
|
||||
resource.discardResponseBody = packet.discardResponseBody;
|
||||
break;
|
||||
case "eventTimings":
|
||||
resource.totalTime = packet.totalTime;
|
||||
break;
|
||||
case "securityInfo":
|
||||
resource.securityState = packet.state;
|
||||
break;
|
||||
case "responseCache":
|
||||
resource.response.responseCache = packet.responseCache;
|
||||
break;
|
||||
}
|
||||
|
||||
onUpdated(resource);
|
||||
|
||||
if (resource.blockedReason) {
|
||||
// Blocked requests
|
||||
if (
|
||||
resource.updates.includes("requestHeaders") &&
|
||||
resource.updates.includes("requestCookies")
|
||||
) {
|
||||
_resources.delete(resource.actor);
|
||||
}
|
||||
} else if (
|
||||
resource.updates.includes("requestHeaders") &&
|
||||
resource.updates.includes("requestCookies") &&
|
||||
resource.updates.includes("eventTimings") &&
|
||||
resource.updates.includes("responseContent")
|
||||
) {
|
||||
_resources.delete(resource.actor);
|
||||
}
|
||||
}
|
||||
|
||||
webConsoleFront.on("serverNetworkEvent", onNetworkEvent);
|
||||
webConsoleFront.on("serverNetworkUpdateEvent", onNetworkEventUpdate);
|
||||
// Start listening to network events
|
||||
webConsoleFront.startListeners(["NetworkActivity"]);
|
||||
};
|
|
@ -34,6 +34,7 @@ class ResourceWatcher {
|
|||
this._onResourceDestroyed = this._onResourceDestroyed.bind(this);
|
||||
|
||||
this._availableListeners = new EventEmitter();
|
||||
this._updatedListeners = new EventEmitter();
|
||||
this._destroyedListeners = new EventEmitter();
|
||||
|
||||
// Cache for all resources by the order that the resource was taken.
|
||||
|
@ -72,6 +73,7 @@ class ResourceWatcher {
|
|||
async watchResources(resources, options) {
|
||||
const {
|
||||
onAvailable,
|
||||
onUpdated,
|
||||
onDestroyed,
|
||||
ignoreExistingResources = false,
|
||||
} = options;
|
||||
|
@ -105,7 +107,9 @@ class ResourceWatcher {
|
|||
await this._startListening(resource);
|
||||
}
|
||||
this._availableListeners.on(resource, onAvailable);
|
||||
|
||||
if (onUpdated) {
|
||||
this._updatedListeners.on(resource, onUpdated);
|
||||
}
|
||||
if (onDestroyed) {
|
||||
this._destroyedListeners.on(resource, onDestroyed);
|
||||
}
|
||||
|
@ -121,9 +125,12 @@ class ResourceWatcher {
|
|||
* See `watchResources` for the arguments as both methods receive the same.
|
||||
*/
|
||||
unwatchResources(resources, options) {
|
||||
const { onAvailable, onDestroyed } = options;
|
||||
const { onAvailable, onUpdated, onDestroyed } = options;
|
||||
|
||||
for (const resource of resources) {
|
||||
if (onUpdated) {
|
||||
this._updatedListeners.off(resource, onUpdated);
|
||||
}
|
||||
if (onDestroyed) {
|
||||
this._destroyedListeners.off(resource, onDestroyed);
|
||||
}
|
||||
|
@ -295,6 +302,27 @@ class ResourceWatcher {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method called either by:
|
||||
* - the backward compatibility code (LegacyListeners)
|
||||
* - target actors RDP events
|
||||
* Called everytime a resource is updated in the remote target.
|
||||
*
|
||||
* @param {Front} targetFront
|
||||
* The Target Front from which this resource comes from.
|
||||
* @param {Array<json/Front>} resources
|
||||
* Depending on the resource Type, it can be an Array composed of either JSON objects or Fronts,
|
||||
* which describes the updated resource.
|
||||
*/
|
||||
_onResourceUpdated(targetFront, resource) {
|
||||
const { resourceType } = resource;
|
||||
this._updatedListeners.emit(resourceType, {
|
||||
resourceType,
|
||||
targetFront,
|
||||
resource,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Called everytime a resource is destroyed in the remote target.
|
||||
* See _onResourceAvailable for the argument description.
|
||||
|
@ -384,11 +412,13 @@ class ResourceWatcher {
|
|||
*/
|
||||
_watchResourcesForTarget(targetFront, resourceType) {
|
||||
const onAvailable = this._onResourceAvailable.bind(this, { targetFront });
|
||||
const onUpdated = this._onResourceUpdated.bind(this, { targetFront });
|
||||
return LegacyListeners[resourceType]({
|
||||
targetList: this.targetList,
|
||||
targetFront,
|
||||
isFissionEnabledOnContentToolbox: gDevTools.isFissionContentToolboxEnabled(),
|
||||
onAvailable,
|
||||
onUpdated,
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -456,6 +486,7 @@ ResourceWatcher.TYPES = ResourceWatcher.prototype.TYPES = {
|
|||
DOCUMENT_EVENT: "document-event",
|
||||
ROOT_NODE: "root-node",
|
||||
STYLESHEET: "stylesheet",
|
||||
NETWORK_EVENT: "network-event",
|
||||
};
|
||||
module.exports = { ResourceWatcher };
|
||||
|
||||
|
@ -494,6 +525,8 @@ const LegacyListeners = {
|
|||
.ROOT_NODE]: require("devtools/shared/resources/legacy-listeners/root-node"),
|
||||
[ResourceWatcher.TYPES
|
||||
.STYLESHEET]: require("devtools/shared/resources/legacy-listeners/stylesheet"),
|
||||
[ResourceWatcher.TYPES
|
||||
.NETWORK_EVENT]: require("devtools/shared/resources/legacy-listeners/network-events"),
|
||||
};
|
||||
|
||||
// Optional transformers for each type of resource.
|
||||
|
|
Загрузка…
Ссылка в новой задаче