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