mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-27 06:43:32 +00:00
Bug 1870580 - added fileChannel observer to netmonitor to display file urls. r=devtools-reviewers,bomsy
Differential Revision: https://phabricator.services.mozilla.com/D191317
This commit is contained in:
parent
81fac6ce12
commit
ab3210c5ce
@ -3,7 +3,7 @@
|
||||
|
||||
"use strict";
|
||||
|
||||
requestLongerTimeout(2);
|
||||
requestLongerTimeout(3);
|
||||
|
||||
/**
|
||||
* Test different text filtering flags
|
||||
|
@ -73,6 +73,26 @@ class NetworkEventActor extends Actor {
|
||||
// Store the channelId which will act as resource id.
|
||||
this._channelId = channel.channelId;
|
||||
|
||||
this._timings = {};
|
||||
this._serverTimings = [];
|
||||
|
||||
this._discardRequestBody = !!networkEventOptions.discardRequestBody;
|
||||
this._discardResponseBody = !!networkEventOptions.discardResponseBody;
|
||||
|
||||
this._response = {
|
||||
headers: [],
|
||||
cookies: [],
|
||||
content: {},
|
||||
};
|
||||
|
||||
if (channel instanceof Ci.nsIFileChannel) {
|
||||
this._innerWindowId = null;
|
||||
this._isNavigationRequest = false;
|
||||
|
||||
this._resource = this._createResource(networkEventOptions, channel);
|
||||
return;
|
||||
}
|
||||
|
||||
// innerWindowId and isNavigationRequest are used to check if the actor
|
||||
// should be destroyed when a window is destroyed. See network-events.js.
|
||||
this._innerWindowId = lazy.NetworkUtils.getChannelInnerWindowId(channel);
|
||||
@ -89,18 +109,6 @@ class NetworkEventActor extends Actor {
|
||||
rawHeaders: networkEventOptions.rawHeaders,
|
||||
};
|
||||
|
||||
this._response = {
|
||||
headers: [],
|
||||
cookies: [],
|
||||
content: {},
|
||||
};
|
||||
|
||||
this._timings = {};
|
||||
this._serverTimings = [];
|
||||
|
||||
this._discardRequestBody = !!networkEventOptions.discardRequestBody;
|
||||
this._discardResponseBody = !!networkEventOptions.discardResponseBody;
|
||||
|
||||
this._resource = this._createResource(networkEventOptions, channel);
|
||||
}
|
||||
|
||||
@ -119,8 +127,18 @@ class NetworkEventActor extends Actor {
|
||||
* Create the resource corresponding to this actor.
|
||||
*/
|
||||
_createResource(networkEventOptions, channel) {
|
||||
channel = channel.QueryInterface(Ci.nsIHttpChannel);
|
||||
const wsChannel = lazy.NetworkUtils.getWebSocketChannel(channel);
|
||||
let wsChannel;
|
||||
let method;
|
||||
if (channel instanceof Ci.nsIFileChannel) {
|
||||
channel = channel.QueryInterface(Ci.nsIFileChannel);
|
||||
channel.QueryInterface(Ci.nsIChannel);
|
||||
wsChannel = null;
|
||||
method = "GET";
|
||||
} else {
|
||||
channel = channel.QueryInterface(Ci.nsIHttpChannel);
|
||||
wsChannel = lazy.NetworkUtils.getWebSocketChannel(channel);
|
||||
method = channel.requestMethod;
|
||||
}
|
||||
|
||||
// Use the WebSocket channel URL for websockets.
|
||||
const url = wsChannel ? wsChannel.URI.spec : channel.URI.spec;
|
||||
@ -188,10 +206,11 @@ class NetworkEventActor extends Actor {
|
||||
fromServiceWorker: networkEventOptions.fromServiceWorker,
|
||||
innerWindowId: this._innerWindowId,
|
||||
isNavigationRequest: this._isNavigationRequest,
|
||||
isFileRequest: channel instanceof Ci.nsIFileChannel,
|
||||
isThirdPartyTrackingResource:
|
||||
lazy.NetworkUtils.isThirdPartyTrackingResource(channel),
|
||||
isXHR,
|
||||
method: channel.requestMethod,
|
||||
method,
|
||||
priority: lazy.NetworkUtils.getChannelPriority(channel),
|
||||
private: lazy.NetworkUtils.isChannelPrivate(channel),
|
||||
referrerPolicy: lazy.NetworkUtils.getReferrerPolicy(channel),
|
||||
@ -451,7 +470,7 @@ class NetworkEventActor extends Actor {
|
||||
// Read response headers and cookies.
|
||||
let responseHeaders = [];
|
||||
let responseCookies = [];
|
||||
if (!this._blockedReason) {
|
||||
if (!this._blockedReason && !(channel instanceof Ci.nsIFileChannel)) {
|
||||
const { cookies, headers } =
|
||||
lazy.NetworkUtils.fetchResponseHeadersAndCookies(channel);
|
||||
responseCookies = cookies;
|
||||
@ -481,10 +500,13 @@ class NetworkEventActor extends Actor {
|
||||
mimeType = contentTypeHeader.value;
|
||||
}
|
||||
|
||||
const timedChannel = channel.QueryInterface(Ci.nsITimedChannel);
|
||||
const waitingTime = Math.round(
|
||||
(timedChannel.responseStartTime - timedChannel.requestStartTime) / 1000
|
||||
);
|
||||
let waitingTime = null;
|
||||
if (!(channel instanceof Ci.nsIFileChannel)) {
|
||||
const timedChannel = channel.QueryInterface(Ci.nsITimedChannel);
|
||||
waitingTime = Math.round(
|
||||
(timedChannel.responseStartTime - timedChannel.requestStartTime) / 1000
|
||||
);
|
||||
}
|
||||
|
||||
let proxyInfo = [];
|
||||
if (proxyResponseRawHeaders) {
|
||||
@ -493,13 +515,16 @@ class NetworkEventActor extends Actor {
|
||||
proxyInfo = proxyResponseRawHeaders.split("\r\n")[0].split(" ");
|
||||
}
|
||||
|
||||
const isFileChannel = channel instanceof Ci.nsIFileChannel;
|
||||
this._onEventUpdate("responseStart", {
|
||||
httpVersion: lazy.NetworkUtils.getHttpVersion(channel),
|
||||
httpVersion: isFileChannel
|
||||
? null
|
||||
: lazy.NetworkUtils.getHttpVersion(channel),
|
||||
mimeType,
|
||||
remoteAddress: fromCache ? "" : channel.remoteAddress,
|
||||
remotePort: fromCache ? "" : channel.remotePort,
|
||||
status: channel.responseStatus + "",
|
||||
statusText: channel.responseStatusText,
|
||||
status: isFileChannel ? "200" : channel.responseStatus + "",
|
||||
statusText: isFileChannel ? "0K" : channel.responseStatusText,
|
||||
waitingTime,
|
||||
isResolvedByTRR: channel.isResolvedByTRR,
|
||||
proxyHttpVersion: proxyInfo[0],
|
||||
|
@ -275,7 +275,7 @@ class NetworkEventWatcher {
|
||||
}
|
||||
|
||||
onNetworkEvent(networkEventOptions, channel) {
|
||||
if (this.networkEvents.has(channel.channelId)) {
|
||||
if (channel.channelId && this.networkEvents.has(channel.channelId)) {
|
||||
throw new Error(
|
||||
`Got notified about channel ${channel.channelId} more than once.`
|
||||
);
|
||||
@ -301,6 +301,7 @@ class NetworkEventWatcher {
|
||||
resourceId: resource.resourceId,
|
||||
resourceType: resource.resourceType,
|
||||
isBlocked,
|
||||
isFileRequest: resource.isFileRequest,
|
||||
receivedUpdates: [],
|
||||
resourceUpdates: {
|
||||
// Requests already come with request cookies and headers, so those
|
||||
@ -375,10 +376,11 @@ class NetworkEventWatcher {
|
||||
resourceUpdates[`${updateResource.updateType}Available`] = true;
|
||||
receivedUpdates.push(updateResource.updateType);
|
||||
|
||||
const isComplete =
|
||||
receivedUpdates.includes("eventTimings") &&
|
||||
receivedUpdates.includes("responseContent") &&
|
||||
receivedUpdates.includes("securityInfo");
|
||||
const isComplete = networkEvent.isFileRequest
|
||||
? receivedUpdates.includes("responseStart")
|
||||
: receivedUpdates.includes("eventTimings") &&
|
||||
receivedUpdates.includes("responseContent") &&
|
||||
receivedUpdates.includes("securityInfo");
|
||||
|
||||
if (isComplete) {
|
||||
this._emitUpdate(networkEvent);
|
||||
|
@ -156,7 +156,7 @@ export class NetworkObserver {
|
||||
*/
|
||||
#onNetworkEvent;
|
||||
/**
|
||||
* Object that holds the HTTP activity objects for ongoing requests.
|
||||
* Object that holds the activity objects for ongoing requests.
|
||||
*
|
||||
* @type {ChannelMap}
|
||||
*/
|
||||
@ -222,6 +222,10 @@ export class NetworkObserver {
|
||||
this.#httpModifyExaminer,
|
||||
"http-on-modify-request"
|
||||
);
|
||||
Services.obs.addObserver(
|
||||
this.#fileChannelExaminer,
|
||||
"file-channel-opened"
|
||||
);
|
||||
Services.obs.addObserver(this.#httpStopRequest, "http-on-stop-request");
|
||||
} else {
|
||||
Services.obs.addObserver(
|
||||
@ -500,6 +504,48 @@ export class NetworkObserver {
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Observe notifications for the file-channel-opened topic
|
||||
*
|
||||
* @private
|
||||
* @param nsIFileChannel subject
|
||||
* @param string topic
|
||||
* @returns void
|
||||
*/
|
||||
#fileChannelExaminer = DevToolsInfaillibleUtils.makeInfallible(
|
||||
(subject, topic) => {
|
||||
if (
|
||||
this.#isDestroyed ||
|
||||
topic != "file-channel-opened" ||
|
||||
!(subject instanceof Ci.nsIFileChannel)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
const channel = subject.QueryInterface(Ci.nsIFileChannel);
|
||||
channel.QueryInterface(Ci.nsIIdentChannel);
|
||||
channel.QueryInterface(Ci.nsIChannel);
|
||||
|
||||
if (this.#ignoreChannelFunction(channel)) {
|
||||
return;
|
||||
}
|
||||
|
||||
logPlatformEvent(topic, channel);
|
||||
|
||||
const fileActivity = this.#createOrGetActivityObject(channel);
|
||||
|
||||
this.#createNetworkEvent(subject, {});
|
||||
|
||||
if (fileActivity.owner) {
|
||||
fileActivity.owner.addResponseStart({
|
||||
channel: fileActivity.channel,
|
||||
fromCache: fileActivity.fromCache || fileActivity.fromServiceWorker,
|
||||
rawHeaders: fileActivity.responseRawHeaders,
|
||||
proxyResponseRawHeaders: fileActivity.proxyResponseRawHeaders,
|
||||
});
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
/**
|
||||
* A helper function for observeActivity. This does whatever work
|
||||
* is required by a particular http activity event. Arguments are
|
||||
@ -666,6 +712,7 @@ export class NetworkObserver {
|
||||
* - Cancel requests blocked by DevTools
|
||||
* - Fetch request headers/cookies
|
||||
* - Set a few attributes on http activity object
|
||||
* - Set a few attributes on file activity object
|
||||
* - Register listener to record response content
|
||||
*/
|
||||
#createNetworkEvent(
|
||||
@ -680,6 +727,21 @@ export class NetworkObserver {
|
||||
inProgressRequest,
|
||||
}
|
||||
) {
|
||||
if (channel instanceof Ci.nsIFileChannel) {
|
||||
const fileActivity = this.#createOrGetActivityObject(channel);
|
||||
|
||||
if (timestamp) {
|
||||
fileActivity.timings.REQUEST_HEADER = {
|
||||
first: timestamp,
|
||||
last: timestamp,
|
||||
};
|
||||
}
|
||||
|
||||
fileActivity.owner = this.#onNetworkEvent({}, channel);
|
||||
|
||||
return fileActivity;
|
||||
}
|
||||
|
||||
const httpActivity = this.#createOrGetActivityObject(channel);
|
||||
|
||||
if (timestamp) {
|
||||
@ -777,7 +839,7 @@ export class NetworkObserver {
|
||||
}
|
||||
|
||||
/**
|
||||
* Find an existing HTTP activity object, or create a new one. This
|
||||
* Find an existing activity object, or create a new one. This
|
||||
* object is used for storing all the request and response
|
||||
* information.
|
||||
*
|
||||
@ -785,26 +847,29 @@ export class NetworkObserver {
|
||||
* this point.
|
||||
*
|
||||
* @see http://www.softwareishard.com/blog/har-12-spec
|
||||
* @param nsIHttpChannel channel
|
||||
* @param {(nsIHttpChannel|nsIFileChannel)} channel
|
||||
* The HTTP channel for which the HTTP activity object is created.
|
||||
* @return object
|
||||
* The new HTTP activity object.
|
||||
*/
|
||||
#createOrGetActivityObject(channel) {
|
||||
let httpActivity = this.#findActivityObject(channel);
|
||||
if (!httpActivity) {
|
||||
const win = lazy.NetworkHelper.getWindowForRequest(channel);
|
||||
const charset = win ? win.document.characterSet : null;
|
||||
let activity = this.#findActivityObject(channel);
|
||||
if (!activity) {
|
||||
const isHttpChannel = channel instanceof Ci.nsIHttpChannel;
|
||||
|
||||
// Most of the data needed from the channel is only available via the
|
||||
// nsIHttpChannelInternal interface.
|
||||
channel.QueryInterface(Ci.nsIHttpChannelInternal);
|
||||
if (isHttpChannel) {
|
||||
// Most of the data needed from the channel is only available via the
|
||||
// nsIHttpChannelInternal interface.
|
||||
channel.QueryInterface(Ci.nsIHttpChannelInternal);
|
||||
} else {
|
||||
channel.QueryInterface(Ci.nsIChannel);
|
||||
}
|
||||
|
||||
httpActivity = {
|
||||
activity = {
|
||||
// The nsIChannel for which this activity object was created.
|
||||
channel,
|
||||
// See #prepareRequestBody()
|
||||
charset,
|
||||
charset: isHttpChannel ? lazy.NetworkUtils.getCharset(channel) : null,
|
||||
// The postData sent by this request.
|
||||
sentBody: null,
|
||||
// The URL for the current channel.
|
||||
@ -813,20 +878,24 @@ export class NetworkObserver {
|
||||
bodySize: 0,
|
||||
// The response headers size.
|
||||
headersSize: 0,
|
||||
// needed for host specific security info
|
||||
hostname: channel.URI.host,
|
||||
discardRequestBody: !this.#saveRequestAndResponseBodies,
|
||||
discardResponseBody: !this.#saveRequestAndResponseBodies,
|
||||
// needed for host specific security info but file urls do not have hostname
|
||||
hostname: isHttpChannel ? channel.URI.host : null,
|
||||
discardRequestBody: isHttpChannel
|
||||
? !this.#saveRequestAndResponseBodies
|
||||
: false,
|
||||
discardResponseBody: isHttpChannel
|
||||
? !this.#saveRequestAndResponseBodies
|
||||
: false,
|
||||
// internal timing information, see observeActivity()
|
||||
timings: {},
|
||||
// the activity owner which is notified when changes happen
|
||||
owner: null,
|
||||
};
|
||||
|
||||
this.#openRequests.set(channel, httpActivity);
|
||||
this.#openRequests.set(channel, activity);
|
||||
}
|
||||
|
||||
return httpActivity;
|
||||
return activity;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1432,6 +1501,10 @@ export class NetworkObserver {
|
||||
this.#httpModifyExaminer,
|
||||
"http-on-modify-request"
|
||||
);
|
||||
Services.obs.removeObserver(
|
||||
this.#fileChannelExaminer,
|
||||
"file-channel-opened"
|
||||
);
|
||||
Services.obs.removeObserver(
|
||||
this.#httpStopRequest,
|
||||
"http-on-stop-request"
|
||||
|
@ -466,7 +466,7 @@ function fetchResponseHeadersAndCookies(channel) {
|
||||
* Check if a given network request should be logged by a network monitor
|
||||
* based on the specified filters.
|
||||
*
|
||||
* @param nsIHttpChannel channel
|
||||
* @param {(nsIHttpChannel|nsIFileChannel)} channel
|
||||
* Request to check.
|
||||
* @param filters
|
||||
* NetworkObserver filters to match against. An object with one of the following attributes:
|
||||
@ -662,6 +662,11 @@ function getBlockedReason(channel, fromCache = false) {
|
||||
return { blockingExtension, blockedReason };
|
||||
}
|
||||
|
||||
function getCharset(channel) {
|
||||
const win = lazy.NetworkHelper.getWindowForRequest(channel);
|
||||
return win ? win.document.characterSet : null;
|
||||
}
|
||||
|
||||
export const NetworkUtils = {
|
||||
causeTypeToString,
|
||||
fetchRequestHeadersAndCookies,
|
||||
@ -684,4 +689,5 @@ export const NetworkUtils = {
|
||||
matchRequest,
|
||||
stringToCauseType,
|
||||
getBlockedReason,
|
||||
getCharset,
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user