mirror of
https://github.com/microsoft/playwright.git
synced 2025-06-26 21:40:17 +00:00
browser(firefox): delete response interception code (#10053)
This commit is contained in:
parent
653e4377a0
commit
091c0065ad
@ -1,2 +1,2 @@
|
|||||||
1302
|
1303
|
||||||
Changed: yurys@chromium.org Mon 01 Nov 2021 05:04:30 PM PDT
|
Changed: yurys@chromium.org Thu 04 Nov 2021 12:26:04 PM PDT
|
||||||
|
|||||||
@ -73,15 +73,8 @@ class PageNetwork {
|
|||||||
this._interceptedRequests.clear();
|
this._interceptedRequests.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
async resumeInterceptedRequest(requestId, url, method, headers, postData, interceptResponse) {
|
resumeInterceptedRequest(requestId, url, method, headers, postData) {
|
||||||
if (interceptResponse) {
|
|
||||||
const intercepted = this._interceptedRequests.get(requestId);
|
|
||||||
if (!intercepted)
|
|
||||||
throw new Error(`Cannot find request "${requestId}"`);
|
|
||||||
return await new ResponseInterceptor(intercepted).interceptResponse(url, method, headers, postData);
|
|
||||||
}
|
|
||||||
this._takeIntercepted(requestId).resume(url, method, headers, postData);
|
this._takeIntercepted(requestId).resume(url, method, headers, postData);
|
||||||
return {};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fulfillInterceptedRequest(requestId, status, statusText, headers, base64body) {
|
fulfillInterceptedRequest(requestId, status, statusText, headers, base64body) {
|
||||||
@ -107,151 +100,6 @@ class PageNetwork {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ResponseInterceptor {
|
|
||||||
constructor(request) {
|
|
||||||
this._originalRequest = request;
|
|
||||||
this._finalRequest = request;
|
|
||||||
this._responseChannel = null;
|
|
||||||
this._interceptedResponse = null;
|
|
||||||
if (request._responseInterceptor)
|
|
||||||
throw new Error('Already intercepting response for this request');
|
|
||||||
request._responseInterceptor = this;
|
|
||||||
}
|
|
||||||
|
|
||||||
async interceptResponse(url, method, headers, postData) {
|
|
||||||
const httpChannel = this._originalRequest.httpChannel;
|
|
||||||
const uri = url ? Services.io.newURI(url) : httpChannel.URI;
|
|
||||||
const newChannel = NetUtil.newChannel({
|
|
||||||
uri,
|
|
||||||
loadingNode: httpChannel.loadInfo.loadingContext,
|
|
||||||
loadingPrincipal: httpChannel.loadInfo.loadingPrincipal || httpChannel.loadInfo.principalToInherit,
|
|
||||||
triggeringPrincipal: httpChannel.loadInfo.triggeringPrincipal,
|
|
||||||
securityFlags: httpChannel.loadInfo.securityFlags,
|
|
||||||
contentPolicyType: httpChannel.loadInfo.internalContentPolicyType,
|
|
||||||
}).QueryInterface(Ci.nsIRequest).QueryInterface(Ci.nsIHttpChannel);
|
|
||||||
newChannel.loadInfo = httpChannel.loadInfo;
|
|
||||||
newChannel.loadGroup = httpChannel.loadGroup;
|
|
||||||
|
|
||||||
for (const header of (headers || requestHeaders(httpChannel)))
|
|
||||||
newChannel.setRequestHeader(header.name, header.value, false /* merge */);
|
|
||||||
|
|
||||||
if (postData) {
|
|
||||||
setPostData(newChannel, postData, headers);
|
|
||||||
} else if (httpChannel instanceof Ci.nsIUploadChannel) {
|
|
||||||
newChannel.QueryInterface(Ci.nsIUploadChannel);
|
|
||||||
newChannel.setUploadStream(httpChannel.uploadStream, '', -1);
|
|
||||||
}
|
|
||||||
// We must set this after setting the upload stream, otherwise it
|
|
||||||
// will always be 'PUT'. (from another place in the source base)
|
|
||||||
newChannel.requestMethod = method || httpChannel.requestMethod;
|
|
||||||
|
|
||||||
this._responseChannel = newChannel;
|
|
||||||
const networkObserver = this._originalRequest._networkObserver;
|
|
||||||
networkObserver._responseInterceptionChannels.add(newChannel);
|
|
||||||
// We add {newChannerl -> original request} mapping so that if the alternative
|
|
||||||
// channel gets redirected we report the redirect on the original(paused)
|
|
||||||
// request.
|
|
||||||
networkObserver._channelToRequest.set(newChannel, this._originalRequest);
|
|
||||||
const pageNetwork = this._originalRequest._pageNetwork;
|
|
||||||
let body;
|
|
||||||
try {
|
|
||||||
body = await new Promise((resolve, reject) => {
|
|
||||||
NetUtil.asyncFetch(newChannel, (stream, status) => {
|
|
||||||
networkObserver._responseInterceptionChannels.delete(newChannel);
|
|
||||||
networkObserver._channelToRequest.delete(newChannel);
|
|
||||||
if (!Components.isSuccessCode(status)) {
|
|
||||||
reject(status);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
resolve(NetUtil.readInputStreamToString(stream, stream.available()));
|
|
||||||
} catch (e) {
|
|
||||||
if (e.result == Cr.NS_BASE_STREAM_CLOSED) {
|
|
||||||
// The stream was empty.
|
|
||||||
resolve('');
|
|
||||||
} else {
|
|
||||||
reject(e.result);
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
stream.close();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
} catch (error) {
|
|
||||||
if (typeof error !== 'number')
|
|
||||||
dump(`ERROR: enexpected error type: ${error}\n`);
|
|
||||||
if (pageNetwork)
|
|
||||||
pageNetwork._interceptedRequests.delete(this._originalRequest.requestId);
|
|
||||||
this._originalRequest._failWithErrorCode(error);
|
|
||||||
return { error: helper.getNetworkErrorStatusText(error) };
|
|
||||||
}
|
|
||||||
|
|
||||||
const finalRequest = this._finalRequest;
|
|
||||||
const responseChannel = finalRequest === this._originalRequest ? this._responseChannel : finalRequest.httpChannel;
|
|
||||||
if (pageNetwork)
|
|
||||||
pageNetwork._responseStorage.addResponseBody(finalRequest, responseChannel, body);
|
|
||||||
const response = responseHead(responseChannel);
|
|
||||||
this._interceptedResponse = Object.assign({ body }, response);
|
|
||||||
return { response };
|
|
||||||
}
|
|
||||||
|
|
||||||
isInterceptedRequest(request) {
|
|
||||||
return this._originalRequest === request;
|
|
||||||
}
|
|
||||||
|
|
||||||
interceptOnResponse(request, fromCache, opt_statusCode, opt_statusText) {
|
|
||||||
const isFullfillingResponse = this._interceptedResponse;
|
|
||||||
if (isFullfillingResponse) {
|
|
||||||
if (request !== this._originalRequest)
|
|
||||||
dump(`ERROR: unexpected request ${request.requestId}, expected ${this._originalRequest.requestId}\n`);
|
|
||||||
this._finalRequest._sendOnResponseImpl(this._originalRequest.httpChannel, fromCache, opt_statusCode, opt_statusText);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// When fetching original response first redirect is reported using original request id
|
|
||||||
// but with data received via the alternative response channel.
|
|
||||||
const httpChannel = (this._originalRequest === request) ? this._responseChannel : request.httpChannel;
|
|
||||||
if (this._isRedirectResponse(httpChannel))
|
|
||||||
request._sendOnResponseImpl(httpChannel, fromCache, opt_statusCode, opt_statusText);
|
|
||||||
// Drop non-redirect response on the floor, it will be fulfilled later.
|
|
||||||
}
|
|
||||||
|
|
||||||
interceptOnRequestFinished(request) {
|
|
||||||
const isFullfillingResponse = this._interceptedResponse;
|
|
||||||
if (isFullfillingResponse) {
|
|
||||||
if (request !== this._originalRequest)
|
|
||||||
dump(`ERROR: unexpected request ${request.requestId}, expected ${this._originalRequest.requestId}\n`);
|
|
||||||
this._finalRequest._sendOnRequestFinishedImpl(this._originalRequest.httpChannel);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// When fetching original response first redirect is reported using original request id
|
|
||||||
// but with data received via the alternative response channel.
|
|
||||||
const httpChannel = (this._originalRequest === request) ? this._responseChannel : request.httpChannel;
|
|
||||||
if (this._isRedirectResponse(httpChannel))
|
|
||||||
request._sendOnRequestFinishedImpl(httpChannel);
|
|
||||||
// Drop non-redirect response on the floor, it will be fulfilled later.
|
|
||||||
}
|
|
||||||
|
|
||||||
interceptOnRequestFailed(error) {
|
|
||||||
this._finalRequest._sendOnRequestFailedImpl(error);
|
|
||||||
}
|
|
||||||
|
|
||||||
interceptAddResponseBody(request, body) {
|
|
||||||
const isFullfillingResponse = this._interceptedResponse;
|
|
||||||
let key = request;
|
|
||||||
if (isFullfillingResponse) {
|
|
||||||
if (request !== this._originalRequest)
|
|
||||||
dump(`ERROR: unexpected request ${request.requestId}, expected ${this._originalRequest.requestId}\n`);
|
|
||||||
key = this._finalRequest;
|
|
||||||
}
|
|
||||||
request._pageNetwork._responseStorage.addResponseBody(key, request.httpChannel, body);
|
|
||||||
}
|
|
||||||
|
|
||||||
_isRedirectResponse(httpChannel) {
|
|
||||||
const status = httpChannel.responseStatus;
|
|
||||||
return (300 <= status && status < 400);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class NetworkRequest {
|
class NetworkRequest {
|
||||||
constructor(networkObserver, httpChannel, redirectedFrom) {
|
constructor(networkObserver, httpChannel, redirectedFrom) {
|
||||||
this._networkObserver = networkObserver;
|
this._networkObserver = networkObserver;
|
||||||
@ -284,10 +132,6 @@ class NetworkRequest {
|
|||||||
// Finish previous request now. Since we inherit the listener, we could in theory
|
// Finish previous request now. Since we inherit the listener, we could in theory
|
||||||
// use onStopRequest, but that will only happen after the last redirect has finished.
|
// use onStopRequest, but that will only happen after the last redirect has finished.
|
||||||
redirectedFrom._sendOnRequestFinished();
|
redirectedFrom._sendOnRequestFinished();
|
||||||
if (redirectedFrom._responseInterceptor) {
|
|
||||||
this._responseInterceptor = redirectedFrom._responseInterceptor;
|
|
||||||
this._responseInterceptor._finalRequest = this;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this._pageNetwork = redirectedFrom ? redirectedFrom._pageNetwork : networkObserver._findPageNetwork(httpChannel);
|
this._pageNetwork = redirectedFrom ? redirectedFrom._pageNetwork : networkObserver._findPageNetwork(httpChannel);
|
||||||
@ -305,10 +149,7 @@ class NetworkRequest {
|
|||||||
|
|
||||||
httpChannel.QueryInterface(Ci.nsITraceableChannel);
|
httpChannel.QueryInterface(Ci.nsITraceableChannel);
|
||||||
this._originalListener = httpChannel.setNewListener(this);
|
this._originalListener = httpChannel.setNewListener(this);
|
||||||
// When fetching original response ResponseInterceptor creates a new HttpChannel
|
if (redirectedFrom) {
|
||||||
// with custom listener which is different from the original request's listener.
|
|
||||||
// In that case we should not inherit the listener from the original request here.
|
|
||||||
if (redirectedFrom && !redirectedFrom._responseInterceptor?.isInterceptedRequest(redirectedFrom)) {
|
|
||||||
// Listener is inherited for regular redirects, so we'd like to avoid
|
// Listener is inherited for regular redirects, so we'd like to avoid
|
||||||
// calling into previous NetworkRequest.
|
// calling into previous NetworkRequest.
|
||||||
this._originalListener = redirectedFrom._originalListener;
|
this._originalListener = redirectedFrom._originalListener;
|
||||||
@ -342,23 +183,12 @@ class NetworkRequest {
|
|||||||
// Public interception API.
|
// Public interception API.
|
||||||
abort(errorCode) {
|
abort(errorCode) {
|
||||||
const error = errorMap[errorCode] || Cr.NS_ERROR_FAILURE;
|
const error = errorMap[errorCode] || Cr.NS_ERROR_FAILURE;
|
||||||
this._failWithErrorCode(error);
|
|
||||||
}
|
|
||||||
|
|
||||||
_failWithErrorCode(error) {
|
|
||||||
this._interceptedChannel.cancelInterception(error);
|
this._interceptedChannel.cancelInterception(error);
|
||||||
this._interceptedChannel = undefined;
|
this._interceptedChannel = undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Public interception API.
|
// Public interception API.
|
||||||
fulfill(status, statusText, headers, base64body) {
|
fulfill(status, statusText, headers, base64body) {
|
||||||
let body = base64body ? atob(base64body) : '';
|
|
||||||
const originalResponse = this._responseInterceptor?._interceptedResponse;
|
|
||||||
if (originalResponse) {
|
|
||||||
status = status || originalResponse.status;
|
|
||||||
statusText = statusText || originalResponse.statusText;
|
|
||||||
headers = headers || originalResponse.headers;
|
|
||||||
}
|
|
||||||
this._interceptedChannel.synthesizeStatus(status, statusText);
|
this._interceptedChannel.synthesizeStatus(status, statusText);
|
||||||
for (const header of headers) {
|
for (const header of headers) {
|
||||||
this._interceptedChannel.synthesizeHeader(header.name, header.value);
|
this._interceptedChannel.synthesizeHeader(header.name, header.value);
|
||||||
@ -368,7 +198,7 @@ class NetworkRequest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
const synthesized = Cc["@mozilla.org/io/string-input-stream;1"].createInstance(Ci.nsIStringInputStream);
|
const synthesized = Cc["@mozilla.org/io/string-input-stream;1"].createInstance(Ci.nsIStringInputStream);
|
||||||
synthesized.data = body;
|
synthesized.data = base64body ? atob(base64body) : '';
|
||||||
this._interceptedChannel.startSynthesizedResponse(synthesized, null, null, '', false);
|
this._interceptedChannel.startSynthesizedResponse(synthesized, null, null, '', false);
|
||||||
this._interceptedChannel.finishSynthesizedResponse();
|
this._interceptedChannel.finishSynthesizedResponse();
|
||||||
this._interceptedChannel = undefined;
|
this._interceptedChannel = undefined;
|
||||||
@ -598,12 +428,8 @@ class NetworkRequest {
|
|||||||
this._sendOnResponse(false);
|
this._sendOnResponse(false);
|
||||||
const body = this._responseBodyChunks.join('');
|
const body = this._responseBodyChunks.join('');
|
||||||
const pageNetwork = this._pageNetwork;
|
const pageNetwork = this._pageNetwork;
|
||||||
if (pageNetwork) {
|
if (pageNetwork)
|
||||||
if (this._responseInterceptor)
|
pageNetwork._responseStorage.addResponseBody(this, body);
|
||||||
this._responseInterceptor.interceptAddResponseBody(this, body);
|
|
||||||
else
|
|
||||||
pageNetwork._responseStorage.addResponseBody(this, this.httpChannel, body);
|
|
||||||
}
|
|
||||||
this._sendOnRequestFinished();
|
this._sendOnRequestFinished();
|
||||||
} else {
|
} else {
|
||||||
this._sendOnRequestFailed(aStatusCode);
|
this._sendOnRequestFailed(aStatusCode);
|
||||||
@ -657,14 +483,6 @@ class NetworkRequest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_sendOnResponse(fromCache, opt_statusCode, opt_statusText) {
|
_sendOnResponse(fromCache, opt_statusCode, opt_statusText) {
|
||||||
if (this._responseInterceptor) {
|
|
||||||
this._responseInterceptor.interceptOnResponse(this, fromCache, opt_statusCode, opt_statusText)
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this._sendOnResponseImpl(this.httpChannel, fromCache, opt_statusCode, opt_statusText);
|
|
||||||
}
|
|
||||||
|
|
||||||
_sendOnResponseImpl(httpChannel, fromCache, opt_statusCode, opt_statusText) {
|
|
||||||
if (this._sentOnResponse) {
|
if (this._sentOnResponse) {
|
||||||
// We can come here twice because of internal redirects, e.g. service workers.
|
// We can come here twice because of internal redirects, e.g. service workers.
|
||||||
return;
|
return;
|
||||||
@ -674,32 +492,32 @@ class NetworkRequest {
|
|||||||
if (!pageNetwork)
|
if (!pageNetwork)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
httpChannel.QueryInterface(Ci.nsIHttpChannelInternal);
|
this.httpChannel.QueryInterface(Ci.nsIHttpChannelInternal);
|
||||||
httpChannel.QueryInterface(Ci.nsITimedChannel);
|
this.httpChannel.QueryInterface(Ci.nsITimedChannel);
|
||||||
const timing = {
|
const timing = {
|
||||||
startTime: httpChannel.channelCreationTime,
|
startTime: this.httpChannel.channelCreationTime,
|
||||||
domainLookupStart: httpChannel.domainLookupStartTime,
|
domainLookupStart: this.httpChannel.domainLookupStartTime,
|
||||||
domainLookupEnd: httpChannel.domainLookupEndTime,
|
domainLookupEnd: this.httpChannel.domainLookupEndTime,
|
||||||
connectStart: httpChannel.connectStartTime,
|
connectStart: this.httpChannel.connectStartTime,
|
||||||
secureConnectionStart: httpChannel.secureConnectionStartTime,
|
secureConnectionStart: this.httpChannel.secureConnectionStartTime,
|
||||||
connectEnd: httpChannel.connectEndTime,
|
connectEnd: this.httpChannel.connectEndTime,
|
||||||
requestStart: httpChannel.requestStartTime,
|
requestStart: this.httpChannel.requestStartTime,
|
||||||
responseStart: httpChannel.responseStartTime,
|
responseStart: this.httpChannel.responseStartTime,
|
||||||
};
|
};
|
||||||
|
|
||||||
const { status, statusText, headers } = responseHead(httpChannel, opt_statusCode, opt_statusText);
|
const { status, statusText, headers } = responseHead(this.httpChannel, opt_statusCode, opt_statusText);
|
||||||
let remoteIPAddress = undefined;
|
let remoteIPAddress = undefined;
|
||||||
let remotePort = undefined;
|
let remotePort = undefined;
|
||||||
try {
|
try {
|
||||||
remoteIPAddress = httpChannel.remoteAddress;
|
remoteIPAddress = this.httpChannel.remoteAddress;
|
||||||
remotePort = httpChannel.remotePort;
|
remotePort = this.httpChannel.remotePort;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// remoteAddress is not defined for cached requests.
|
// remoteAddress is not defined for cached requests.
|
||||||
}
|
}
|
||||||
|
|
||||||
pageNetwork.emit(PageNetwork.Events.Response, {
|
pageNetwork.emit(PageNetwork.Events.Response, {
|
||||||
requestId: this.requestId,
|
requestId: this.requestId,
|
||||||
securityDetails: getSecurityDetails(httpChannel),
|
securityDetails: getSecurityDetails(this.httpChannel),
|
||||||
fromCache,
|
fromCache,
|
||||||
headers,
|
headers,
|
||||||
remoteIPAddress,
|
remoteIPAddress,
|
||||||
@ -711,14 +529,6 @@ class NetworkRequest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_sendOnRequestFailed(error) {
|
_sendOnRequestFailed(error) {
|
||||||
if (this._responseInterceptor) {
|
|
||||||
this._responseInterceptor.interceptOnRequestFailed(error);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this._sendOnRequestFailedImpl(error);
|
|
||||||
}
|
|
||||||
|
|
||||||
_sendOnRequestFailedImpl(error) {
|
|
||||||
const pageNetwork = this._pageNetwork;
|
const pageNetwork = this._pageNetwork;
|
||||||
if (pageNetwork) {
|
if (pageNetwork) {
|
||||||
pageNetwork.emit(PageNetwork.Events.RequestFailed, {
|
pageNetwork.emit(PageNetwork.Events.RequestFailed, {
|
||||||
@ -730,25 +540,17 @@ class NetworkRequest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_sendOnRequestFinished() {
|
_sendOnRequestFinished() {
|
||||||
if (this._responseInterceptor) {
|
|
||||||
this._responseInterceptor.interceptOnRequestFinished(this);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this._sendOnRequestFinishedImpl(this.httpChannel);
|
|
||||||
}
|
|
||||||
|
|
||||||
_sendOnRequestFinishedImpl(httpChannel) {
|
|
||||||
const pageNetwork = this._pageNetwork;
|
const pageNetwork = this._pageNetwork;
|
||||||
if (pageNetwork) {
|
if (pageNetwork) {
|
||||||
pageNetwork.emit(PageNetwork.Events.RequestFinished, {
|
pageNetwork.emit(PageNetwork.Events.RequestFinished, {
|
||||||
requestId: this.requestId,
|
requestId: this.requestId,
|
||||||
responseEndTime: httpChannel.responseEndTime,
|
responseEndTime: this.httpChannel.responseEndTime,
|
||||||
transferSize: httpChannel.transferSize,
|
transferSize: this.httpChannel.transferSize,
|
||||||
encodedBodySize: httpChannel.encodedBodySize,
|
encodedBodySize: this.httpChannel.encodedBodySize,
|
||||||
protocolVersion: httpChannel.protocolVersion,
|
protocolVersion: this.httpChannel.protocolVersion,
|
||||||
}, this._frameId);
|
}, this._frameId);
|
||||||
}
|
}
|
||||||
this._networkObserver._channelToRequest.delete(httpChannel);
|
this._networkObserver._channelToRequest.delete(this.httpChannel);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -765,7 +567,6 @@ class NetworkObserver {
|
|||||||
|
|
||||||
this._channelToRequest = new Map(); // http channel -> network request
|
this._channelToRequest = new Map(); // http channel -> network request
|
||||||
this._expectedRedirect = new Map(); // expected redirect channel id (string) -> network request
|
this._expectedRedirect = new Map(); // expected redirect channel id (string) -> network request
|
||||||
this._responseInterceptionChannels = new Set(); // http channels created for response interception
|
|
||||||
|
|
||||||
const protocolProxyService = Cc['@mozilla.org/network/protocol-proxy-service;1'].getService();
|
const protocolProxyService = Cc['@mozilla.org/network/protocol-proxy-service;1'].getService();
|
||||||
this._channelProxyFilter = {
|
this._channelProxyFilter = {
|
||||||
@ -854,8 +655,6 @@ class NetworkObserver {
|
|||||||
_onRequest(channel, topic) {
|
_onRequest(channel, topic) {
|
||||||
if (!(channel instanceof Ci.nsIHttpChannel))
|
if (!(channel instanceof Ci.nsIHttpChannel))
|
||||||
return;
|
return;
|
||||||
if (this._responseInterceptionChannels.has(channel))
|
|
||||||
return;
|
|
||||||
const httpChannel = channel.QueryInterface(Ci.nsIHttpChannel);
|
const httpChannel = channel.QueryInterface(Ci.nsIHttpChannel);
|
||||||
const channelId = httpChannel.channelId + '';
|
const channelId = httpChannel.channelId + '';
|
||||||
const redirectedFrom = this._expectedRedirect.get(channelId);
|
const redirectedFrom = this._expectedRedirect.get(channelId);
|
||||||
@ -982,7 +781,7 @@ class ResponseStorage {
|
|||||||
this._responses = new Map();
|
this._responses = new Map();
|
||||||
}
|
}
|
||||||
|
|
||||||
addResponseBody(request, httpChannel, body) {
|
addResponseBody(request, body) {
|
||||||
if (body.length > this._maxResponseSize) {
|
if (body.length > this._maxResponseSize) {
|
||||||
this._responses.set(request.requestId, {
|
this._responses.set(request.requestId, {
|
||||||
evicted: true,
|
evicted: true,
|
||||||
@ -991,8 +790,8 @@ class ResponseStorage {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let encodings = [];
|
let encodings = [];
|
||||||
if ((httpChannel instanceof Ci.nsIEncodedChannel) && httpChannel.contentEncodings && !httpChannel.applyConversion) {
|
if ((request.httpChannel instanceof Ci.nsIEncodedChannel) && request.httpChannel.contentEncodings && !request.httpChannel.applyConversion) {
|
||||||
const encodingHeader = httpChannel.getResponseHeader("Content-Encoding");
|
const encodingHeader = request.httpChannel.getResponseHeader("Content-Encoding");
|
||||||
encodings = encodingHeader.split(/\s*\t*,\s*\t*/);
|
encodings = encodingHeader.split(/\s*\t*,\s*\t*/);
|
||||||
}
|
}
|
||||||
this._responses.set(request.requestId, {body, encodings});
|
this._responses.set(request.requestId, {body, encodings});
|
||||||
|
|||||||
@ -259,8 +259,8 @@ class PageHandler {
|
|||||||
this._pageNetwork.disableRequestInterception();
|
this._pageNetwork.disableRequestInterception();
|
||||||
}
|
}
|
||||||
|
|
||||||
async ['Network.resumeInterceptedRequest']({requestId, url, method, headers, postData, interceptResponse}) {
|
async ['Network.resumeInterceptedRequest']({requestId, url, method, headers, postData}) {
|
||||||
return await this._pageNetwork.resumeInterceptedRequest(requestId, url, method, headers, postData, interceptResponse);
|
this._pageNetwork.resumeInterceptedRequest(requestId, url, method, headers, postData);
|
||||||
}
|
}
|
||||||
|
|
||||||
async ['Network.abortInterceptedRequest']({requestId, errorCode}) {
|
async ['Network.abortInterceptedRequest']({requestId, errorCode}) {
|
||||||
|
|||||||
@ -205,12 +205,6 @@ networkTypes.ResourceTiming = {
|
|||||||
responseStart: t.Number,
|
responseStart: t.Number,
|
||||||
};
|
};
|
||||||
|
|
||||||
networkTypes.InterceptedResponse = {
|
|
||||||
status: t.Number,
|
|
||||||
statusText: t.String,
|
|
||||||
headers: t.Array(networkTypes.HTTPHeader),
|
|
||||||
};
|
|
||||||
|
|
||||||
const Browser = {
|
const Browser = {
|
||||||
targets: ['browser'],
|
targets: ['browser'],
|
||||||
|
|
||||||
@ -540,11 +534,6 @@ const Network = {
|
|||||||
method: t.Optional(t.String),
|
method: t.Optional(t.String),
|
||||||
headers: t.Optional(t.Array(networkTypes.HTTPHeader)),
|
headers: t.Optional(t.Array(networkTypes.HTTPHeader)),
|
||||||
postData: t.Optional(t.String),
|
postData: t.Optional(t.String),
|
||||||
interceptResponse: t.Optional(t.Boolean),
|
|
||||||
},
|
|
||||||
returns: {
|
|
||||||
response: t.Optional(networkTypes.InterceptedResponse),
|
|
||||||
error: t.Optional(t.String),
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
'fulfillInterceptedRequest': {
|
'fulfillInterceptedRequest': {
|
||||||
|
|||||||
@ -1,2 +1,2 @@
|
|||||||
1301
|
1302
|
||||||
Changed: lushnikov@chromium.org Thu Nov 4 08:24:38 HST 2021
|
Changed: yurys@chromium.org Thu 04 Nov 2021 12:24:04 PM PDT
|
||||||
|
|||||||
@ -73,15 +73,8 @@ class PageNetwork {
|
|||||||
this._interceptedRequests.clear();
|
this._interceptedRequests.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
async resumeInterceptedRequest(requestId, url, method, headers, postData, interceptResponse) {
|
resumeInterceptedRequest(requestId, url, method, headers, postData) {
|
||||||
if (interceptResponse) {
|
|
||||||
const intercepted = this._interceptedRequests.get(requestId);
|
|
||||||
if (!intercepted)
|
|
||||||
throw new Error(`Cannot find request "${requestId}"`);
|
|
||||||
return await new ResponseInterceptor(intercepted).interceptResponse(url, method, headers, postData);
|
|
||||||
}
|
|
||||||
this._takeIntercepted(requestId).resume(url, method, headers, postData);
|
this._takeIntercepted(requestId).resume(url, method, headers, postData);
|
||||||
return {};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fulfillInterceptedRequest(requestId, status, statusText, headers, base64body) {
|
fulfillInterceptedRequest(requestId, status, statusText, headers, base64body) {
|
||||||
@ -107,151 +100,6 @@ class PageNetwork {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ResponseInterceptor {
|
|
||||||
constructor(request) {
|
|
||||||
this._originalRequest = request;
|
|
||||||
this._finalRequest = request;
|
|
||||||
this._responseChannel = null;
|
|
||||||
this._interceptedResponse = null;
|
|
||||||
if (request._responseInterceptor)
|
|
||||||
throw new Error('Already intercepting response for this request');
|
|
||||||
request._responseInterceptor = this;
|
|
||||||
}
|
|
||||||
|
|
||||||
async interceptResponse(url, method, headers, postData) {
|
|
||||||
const httpChannel = this._originalRequest.httpChannel;
|
|
||||||
const uri = url ? Services.io.newURI(url) : httpChannel.URI;
|
|
||||||
const newChannel = NetUtil.newChannel({
|
|
||||||
uri,
|
|
||||||
loadingNode: httpChannel.loadInfo.loadingContext,
|
|
||||||
loadingPrincipal: httpChannel.loadInfo.loadingPrincipal || httpChannel.loadInfo.principalToInherit,
|
|
||||||
triggeringPrincipal: httpChannel.loadInfo.triggeringPrincipal,
|
|
||||||
securityFlags: httpChannel.loadInfo.securityFlags,
|
|
||||||
contentPolicyType: httpChannel.loadInfo.internalContentPolicyType,
|
|
||||||
}).QueryInterface(Ci.nsIRequest).QueryInterface(Ci.nsIHttpChannel);
|
|
||||||
newChannel.loadInfo = httpChannel.loadInfo;
|
|
||||||
newChannel.loadGroup = httpChannel.loadGroup;
|
|
||||||
|
|
||||||
for (const header of (headers || requestHeaders(httpChannel)))
|
|
||||||
newChannel.setRequestHeader(header.name, header.value, false /* merge */);
|
|
||||||
|
|
||||||
if (postData) {
|
|
||||||
setPostData(newChannel, postData, headers);
|
|
||||||
} else if (httpChannel instanceof Ci.nsIUploadChannel) {
|
|
||||||
newChannel.QueryInterface(Ci.nsIUploadChannel);
|
|
||||||
newChannel.setUploadStream(httpChannel.uploadStream, '', -1);
|
|
||||||
}
|
|
||||||
// We must set this after setting the upload stream, otherwise it
|
|
||||||
// will always be 'PUT'. (from another place in the source base)
|
|
||||||
newChannel.requestMethod = method || httpChannel.requestMethod;
|
|
||||||
|
|
||||||
this._responseChannel = newChannel;
|
|
||||||
const networkObserver = this._originalRequest._networkObserver;
|
|
||||||
networkObserver._responseInterceptionChannels.add(newChannel);
|
|
||||||
// We add {newChannerl -> original request} mapping so that if the alternative
|
|
||||||
// channel gets redirected we report the redirect on the original(paused)
|
|
||||||
// request.
|
|
||||||
networkObserver._channelToRequest.set(newChannel, this._originalRequest);
|
|
||||||
const pageNetwork = this._originalRequest._pageNetwork;
|
|
||||||
let body;
|
|
||||||
try {
|
|
||||||
body = await new Promise((resolve, reject) => {
|
|
||||||
NetUtil.asyncFetch(newChannel, (stream, status) => {
|
|
||||||
networkObserver._responseInterceptionChannels.delete(newChannel);
|
|
||||||
networkObserver._channelToRequest.delete(newChannel);
|
|
||||||
if (!Components.isSuccessCode(status)) {
|
|
||||||
reject(status);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
resolve(NetUtil.readInputStreamToString(stream, stream.available()));
|
|
||||||
} catch (e) {
|
|
||||||
if (e.result == Cr.NS_BASE_STREAM_CLOSED) {
|
|
||||||
// The stream was empty.
|
|
||||||
resolve('');
|
|
||||||
} else {
|
|
||||||
reject(e.result);
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
stream.close();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
} catch (error) {
|
|
||||||
if (typeof error !== 'number')
|
|
||||||
dump(`ERROR: enexpected error type: ${error}\n`);
|
|
||||||
if (pageNetwork)
|
|
||||||
pageNetwork._interceptedRequests.delete(this._originalRequest.requestId);
|
|
||||||
this._originalRequest._failWithErrorCode(error);
|
|
||||||
return { error: helper.getNetworkErrorStatusText(error) };
|
|
||||||
}
|
|
||||||
|
|
||||||
const finalRequest = this._finalRequest;
|
|
||||||
const responseChannel = finalRequest === this._originalRequest ? this._responseChannel : finalRequest.httpChannel;
|
|
||||||
if (pageNetwork)
|
|
||||||
pageNetwork._responseStorage.addResponseBody(finalRequest, responseChannel, body);
|
|
||||||
const response = responseHead(responseChannel);
|
|
||||||
this._interceptedResponse = Object.assign({ body }, response);
|
|
||||||
return { response };
|
|
||||||
}
|
|
||||||
|
|
||||||
isInterceptedRequest(request) {
|
|
||||||
return this._originalRequest === request;
|
|
||||||
}
|
|
||||||
|
|
||||||
interceptOnResponse(request, fromCache, opt_statusCode, opt_statusText) {
|
|
||||||
const isFullfillingResponse = this._interceptedResponse;
|
|
||||||
if (isFullfillingResponse) {
|
|
||||||
if (request !== this._originalRequest)
|
|
||||||
dump(`ERROR: unexpected request ${request.requestId}, expected ${this._originalRequest.requestId}\n`);
|
|
||||||
this._finalRequest._sendOnResponseImpl(this._originalRequest.httpChannel, fromCache, opt_statusCode, opt_statusText);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// When fetching original response first redirect is reported using original request id
|
|
||||||
// but with data received via the alternative response channel.
|
|
||||||
const httpChannel = (this._originalRequest === request) ? this._responseChannel : request.httpChannel;
|
|
||||||
if (this._isRedirectResponse(httpChannel))
|
|
||||||
request._sendOnResponseImpl(httpChannel, fromCache, opt_statusCode, opt_statusText);
|
|
||||||
// Drop non-redirect response on the floor, it will be fulfilled later.
|
|
||||||
}
|
|
||||||
|
|
||||||
interceptOnRequestFinished(request) {
|
|
||||||
const isFullfillingResponse = this._interceptedResponse;
|
|
||||||
if (isFullfillingResponse) {
|
|
||||||
if (request !== this._originalRequest)
|
|
||||||
dump(`ERROR: unexpected request ${request.requestId}, expected ${this._originalRequest.requestId}\n`);
|
|
||||||
this._finalRequest._sendOnRequestFinishedImpl(this._originalRequest.httpChannel);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// When fetching original response first redirect is reported using original request id
|
|
||||||
// but with data received via the alternative response channel.
|
|
||||||
const httpChannel = (this._originalRequest === request) ? this._responseChannel : request.httpChannel;
|
|
||||||
if (this._isRedirectResponse(httpChannel))
|
|
||||||
request._sendOnRequestFinishedImpl(httpChannel);
|
|
||||||
// Drop non-redirect response on the floor, it will be fulfilled later.
|
|
||||||
}
|
|
||||||
|
|
||||||
interceptOnRequestFailed(error) {
|
|
||||||
this._finalRequest._sendOnRequestFailedImpl(error);
|
|
||||||
}
|
|
||||||
|
|
||||||
interceptAddResponseBody(request, body) {
|
|
||||||
const isFullfillingResponse = this._interceptedResponse;
|
|
||||||
let key = request;
|
|
||||||
if (isFullfillingResponse) {
|
|
||||||
if (request !== this._originalRequest)
|
|
||||||
dump(`ERROR: unexpected request ${request.requestId}, expected ${this._originalRequest.requestId}\n`);
|
|
||||||
key = this._finalRequest;
|
|
||||||
}
|
|
||||||
request._pageNetwork._responseStorage.addResponseBody(key, request.httpChannel, body);
|
|
||||||
}
|
|
||||||
|
|
||||||
_isRedirectResponse(httpChannel) {
|
|
||||||
const status = httpChannel.responseStatus;
|
|
||||||
return (300 <= status && status < 400);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class NetworkRequest {
|
class NetworkRequest {
|
||||||
constructor(networkObserver, httpChannel, redirectedFrom) {
|
constructor(networkObserver, httpChannel, redirectedFrom) {
|
||||||
this._networkObserver = networkObserver;
|
this._networkObserver = networkObserver;
|
||||||
@ -284,10 +132,6 @@ class NetworkRequest {
|
|||||||
// Finish previous request now. Since we inherit the listener, we could in theory
|
// Finish previous request now. Since we inherit the listener, we could in theory
|
||||||
// use onStopRequest, but that will only happen after the last redirect has finished.
|
// use onStopRequest, but that will only happen after the last redirect has finished.
|
||||||
redirectedFrom._sendOnRequestFinished();
|
redirectedFrom._sendOnRequestFinished();
|
||||||
if (redirectedFrom._responseInterceptor) {
|
|
||||||
this._responseInterceptor = redirectedFrom._responseInterceptor;
|
|
||||||
this._responseInterceptor._finalRequest = this;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this._pageNetwork = redirectedFrom ? redirectedFrom._pageNetwork : networkObserver._findPageNetwork(httpChannel);
|
this._pageNetwork = redirectedFrom ? redirectedFrom._pageNetwork : networkObserver._findPageNetwork(httpChannel);
|
||||||
@ -305,10 +149,7 @@ class NetworkRequest {
|
|||||||
|
|
||||||
httpChannel.QueryInterface(Ci.nsITraceableChannel);
|
httpChannel.QueryInterface(Ci.nsITraceableChannel);
|
||||||
this._originalListener = httpChannel.setNewListener(this);
|
this._originalListener = httpChannel.setNewListener(this);
|
||||||
// When fetching original response ResponseInterceptor creates a new HttpChannel
|
if (redirectedFrom) {
|
||||||
// with custom listener which is different from the original request's listener.
|
|
||||||
// In that case we should not inherit the listener from the original request here.
|
|
||||||
if (redirectedFrom && !redirectedFrom._responseInterceptor?.isInterceptedRequest(redirectedFrom)) {
|
|
||||||
// Listener is inherited for regular redirects, so we'd like to avoid
|
// Listener is inherited for regular redirects, so we'd like to avoid
|
||||||
// calling into previous NetworkRequest.
|
// calling into previous NetworkRequest.
|
||||||
this._originalListener = redirectedFrom._originalListener;
|
this._originalListener = redirectedFrom._originalListener;
|
||||||
@ -342,23 +183,12 @@ class NetworkRequest {
|
|||||||
// Public interception API.
|
// Public interception API.
|
||||||
abort(errorCode) {
|
abort(errorCode) {
|
||||||
const error = errorMap[errorCode] || Cr.NS_ERROR_FAILURE;
|
const error = errorMap[errorCode] || Cr.NS_ERROR_FAILURE;
|
||||||
this._failWithErrorCode(error);
|
|
||||||
}
|
|
||||||
|
|
||||||
_failWithErrorCode(error) {
|
|
||||||
this._interceptedChannel.cancelInterception(error);
|
this._interceptedChannel.cancelInterception(error);
|
||||||
this._interceptedChannel = undefined;
|
this._interceptedChannel = undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Public interception API.
|
// Public interception API.
|
||||||
fulfill(status, statusText, headers, base64body) {
|
fulfill(status, statusText, headers, base64body) {
|
||||||
let body = base64body ? atob(base64body) : '';
|
|
||||||
const originalResponse = this._responseInterceptor?._interceptedResponse;
|
|
||||||
if (originalResponse) {
|
|
||||||
status = status || originalResponse.status;
|
|
||||||
statusText = statusText || originalResponse.statusText;
|
|
||||||
headers = headers || originalResponse.headers;
|
|
||||||
}
|
|
||||||
this._interceptedChannel.synthesizeStatus(status, statusText);
|
this._interceptedChannel.synthesizeStatus(status, statusText);
|
||||||
for (const header of headers) {
|
for (const header of headers) {
|
||||||
this._interceptedChannel.synthesizeHeader(header.name, header.value);
|
this._interceptedChannel.synthesizeHeader(header.name, header.value);
|
||||||
@ -368,7 +198,7 @@ class NetworkRequest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
const synthesized = Cc["@mozilla.org/io/string-input-stream;1"].createInstance(Ci.nsIStringInputStream);
|
const synthesized = Cc["@mozilla.org/io/string-input-stream;1"].createInstance(Ci.nsIStringInputStream);
|
||||||
synthesized.data = body;
|
synthesized.data = base64body ? atob(base64body) : '';
|
||||||
this._interceptedChannel.startSynthesizedResponse(synthesized, null, null, '', false);
|
this._interceptedChannel.startSynthesizedResponse(synthesized, null, null, '', false);
|
||||||
this._interceptedChannel.finishSynthesizedResponse();
|
this._interceptedChannel.finishSynthesizedResponse();
|
||||||
this._interceptedChannel = undefined;
|
this._interceptedChannel = undefined;
|
||||||
@ -598,12 +428,8 @@ class NetworkRequest {
|
|||||||
this._sendOnResponse(false);
|
this._sendOnResponse(false);
|
||||||
const body = this._responseBodyChunks.join('');
|
const body = this._responseBodyChunks.join('');
|
||||||
const pageNetwork = this._pageNetwork;
|
const pageNetwork = this._pageNetwork;
|
||||||
if (pageNetwork) {
|
if (pageNetwork)
|
||||||
if (this._responseInterceptor)
|
pageNetwork._responseStorage.addResponseBody(this, body);
|
||||||
this._responseInterceptor.interceptAddResponseBody(this, body);
|
|
||||||
else
|
|
||||||
pageNetwork._responseStorage.addResponseBody(this, this.httpChannel, body);
|
|
||||||
}
|
|
||||||
this._sendOnRequestFinished();
|
this._sendOnRequestFinished();
|
||||||
} else {
|
} else {
|
||||||
this._sendOnRequestFailed(aStatusCode);
|
this._sendOnRequestFailed(aStatusCode);
|
||||||
@ -657,14 +483,6 @@ class NetworkRequest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_sendOnResponse(fromCache, opt_statusCode, opt_statusText) {
|
_sendOnResponse(fromCache, opt_statusCode, opt_statusText) {
|
||||||
if (this._responseInterceptor) {
|
|
||||||
this._responseInterceptor.interceptOnResponse(this, fromCache, opt_statusCode, opt_statusText)
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this._sendOnResponseImpl(this.httpChannel, fromCache, opt_statusCode, opt_statusText);
|
|
||||||
}
|
|
||||||
|
|
||||||
_sendOnResponseImpl(httpChannel, fromCache, opt_statusCode, opt_statusText) {
|
|
||||||
if (this._sentOnResponse) {
|
if (this._sentOnResponse) {
|
||||||
// We can come here twice because of internal redirects, e.g. service workers.
|
// We can come here twice because of internal redirects, e.g. service workers.
|
||||||
return;
|
return;
|
||||||
@ -674,32 +492,32 @@ class NetworkRequest {
|
|||||||
if (!pageNetwork)
|
if (!pageNetwork)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
httpChannel.QueryInterface(Ci.nsIHttpChannelInternal);
|
this.httpChannel.QueryInterface(Ci.nsIHttpChannelInternal);
|
||||||
httpChannel.QueryInterface(Ci.nsITimedChannel);
|
this.httpChannel.QueryInterface(Ci.nsITimedChannel);
|
||||||
const timing = {
|
const timing = {
|
||||||
startTime: httpChannel.channelCreationTime,
|
startTime: this.httpChannel.channelCreationTime,
|
||||||
domainLookupStart: httpChannel.domainLookupStartTime,
|
domainLookupStart: this.httpChannel.domainLookupStartTime,
|
||||||
domainLookupEnd: httpChannel.domainLookupEndTime,
|
domainLookupEnd: this.httpChannel.domainLookupEndTime,
|
||||||
connectStart: httpChannel.connectStartTime,
|
connectStart: this.httpChannel.connectStartTime,
|
||||||
secureConnectionStart: httpChannel.secureConnectionStartTime,
|
secureConnectionStart: this.httpChannel.secureConnectionStartTime,
|
||||||
connectEnd: httpChannel.connectEndTime,
|
connectEnd: this.httpChannel.connectEndTime,
|
||||||
requestStart: httpChannel.requestStartTime,
|
requestStart: this.httpChannel.requestStartTime,
|
||||||
responseStart: httpChannel.responseStartTime,
|
responseStart: this.httpChannel.responseStartTime,
|
||||||
};
|
};
|
||||||
|
|
||||||
const { status, statusText, headers } = responseHead(httpChannel, opt_statusCode, opt_statusText);
|
const { status, statusText, headers } = responseHead(this.httpChannel, opt_statusCode, opt_statusText);
|
||||||
let remoteIPAddress = undefined;
|
let remoteIPAddress = undefined;
|
||||||
let remotePort = undefined;
|
let remotePort = undefined;
|
||||||
try {
|
try {
|
||||||
remoteIPAddress = httpChannel.remoteAddress;
|
remoteIPAddress = this.httpChannel.remoteAddress;
|
||||||
remotePort = httpChannel.remotePort;
|
remotePort = this.httpChannel.remotePort;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// remoteAddress is not defined for cached requests.
|
// remoteAddress is not defined for cached requests.
|
||||||
}
|
}
|
||||||
|
|
||||||
pageNetwork.emit(PageNetwork.Events.Response, {
|
pageNetwork.emit(PageNetwork.Events.Response, {
|
||||||
requestId: this.requestId,
|
requestId: this.requestId,
|
||||||
securityDetails: getSecurityDetails(httpChannel),
|
securityDetails: getSecurityDetails(this.httpChannel),
|
||||||
fromCache,
|
fromCache,
|
||||||
headers,
|
headers,
|
||||||
remoteIPAddress,
|
remoteIPAddress,
|
||||||
@ -711,14 +529,6 @@ class NetworkRequest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_sendOnRequestFailed(error) {
|
_sendOnRequestFailed(error) {
|
||||||
if (this._responseInterceptor) {
|
|
||||||
this._responseInterceptor.interceptOnRequestFailed(error);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this._sendOnRequestFailedImpl(error);
|
|
||||||
}
|
|
||||||
|
|
||||||
_sendOnRequestFailedImpl(error) {
|
|
||||||
const pageNetwork = this._pageNetwork;
|
const pageNetwork = this._pageNetwork;
|
||||||
if (pageNetwork) {
|
if (pageNetwork) {
|
||||||
pageNetwork.emit(PageNetwork.Events.RequestFailed, {
|
pageNetwork.emit(PageNetwork.Events.RequestFailed, {
|
||||||
@ -730,25 +540,17 @@ class NetworkRequest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_sendOnRequestFinished() {
|
_sendOnRequestFinished() {
|
||||||
if (this._responseInterceptor) {
|
|
||||||
this._responseInterceptor.interceptOnRequestFinished(this);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this._sendOnRequestFinishedImpl(this.httpChannel);
|
|
||||||
}
|
|
||||||
|
|
||||||
_sendOnRequestFinishedImpl(httpChannel) {
|
|
||||||
const pageNetwork = this._pageNetwork;
|
const pageNetwork = this._pageNetwork;
|
||||||
if (pageNetwork) {
|
if (pageNetwork) {
|
||||||
pageNetwork.emit(PageNetwork.Events.RequestFinished, {
|
pageNetwork.emit(PageNetwork.Events.RequestFinished, {
|
||||||
requestId: this.requestId,
|
requestId: this.requestId,
|
||||||
responseEndTime: httpChannel.responseEndTime,
|
responseEndTime: this.httpChannel.responseEndTime,
|
||||||
transferSize: httpChannel.transferSize,
|
transferSize: this.httpChannel.transferSize,
|
||||||
encodedBodySize: httpChannel.encodedBodySize,
|
encodedBodySize: this.httpChannel.encodedBodySize,
|
||||||
protocolVersion: httpChannel.protocolVersion,
|
protocolVersion: this.httpChannel.protocolVersion,
|
||||||
}, this._frameId);
|
}, this._frameId);
|
||||||
}
|
}
|
||||||
this._networkObserver._channelToRequest.delete(httpChannel);
|
this._networkObserver._channelToRequest.delete(this.httpChannel);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -765,7 +567,6 @@ class NetworkObserver {
|
|||||||
|
|
||||||
this._channelToRequest = new Map(); // http channel -> network request
|
this._channelToRequest = new Map(); // http channel -> network request
|
||||||
this._expectedRedirect = new Map(); // expected redirect channel id (string) -> network request
|
this._expectedRedirect = new Map(); // expected redirect channel id (string) -> network request
|
||||||
this._responseInterceptionChannels = new Set(); // http channels created for response interception
|
|
||||||
|
|
||||||
const protocolProxyService = Cc['@mozilla.org/network/protocol-proxy-service;1'].getService();
|
const protocolProxyService = Cc['@mozilla.org/network/protocol-proxy-service;1'].getService();
|
||||||
this._channelProxyFilter = {
|
this._channelProxyFilter = {
|
||||||
@ -854,8 +655,6 @@ class NetworkObserver {
|
|||||||
_onRequest(channel, topic) {
|
_onRequest(channel, topic) {
|
||||||
if (!(channel instanceof Ci.nsIHttpChannel))
|
if (!(channel instanceof Ci.nsIHttpChannel))
|
||||||
return;
|
return;
|
||||||
if (this._responseInterceptionChannels.has(channel))
|
|
||||||
return;
|
|
||||||
const httpChannel = channel.QueryInterface(Ci.nsIHttpChannel);
|
const httpChannel = channel.QueryInterface(Ci.nsIHttpChannel);
|
||||||
const channelId = httpChannel.channelId + '';
|
const channelId = httpChannel.channelId + '';
|
||||||
const redirectedFrom = this._expectedRedirect.get(channelId);
|
const redirectedFrom = this._expectedRedirect.get(channelId);
|
||||||
@ -982,7 +781,7 @@ class ResponseStorage {
|
|||||||
this._responses = new Map();
|
this._responses = new Map();
|
||||||
}
|
}
|
||||||
|
|
||||||
addResponseBody(request, httpChannel, body) {
|
addResponseBody(request, body) {
|
||||||
if (body.length > this._maxResponseSize) {
|
if (body.length > this._maxResponseSize) {
|
||||||
this._responses.set(request.requestId, {
|
this._responses.set(request.requestId, {
|
||||||
evicted: true,
|
evicted: true,
|
||||||
@ -991,8 +790,8 @@ class ResponseStorage {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let encodings = [];
|
let encodings = [];
|
||||||
if ((httpChannel instanceof Ci.nsIEncodedChannel) && httpChannel.contentEncodings && !httpChannel.applyConversion) {
|
if ((request.httpChannel instanceof Ci.nsIEncodedChannel) && request.httpChannel.contentEncodings && !request.httpChannel.applyConversion) {
|
||||||
const encodingHeader = httpChannel.getResponseHeader("Content-Encoding");
|
const encodingHeader = request.httpChannel.getResponseHeader("Content-Encoding");
|
||||||
encodings = encodingHeader.split(/\s*\t*,\s*\t*/);
|
encodings = encodingHeader.split(/\s*\t*,\s*\t*/);
|
||||||
}
|
}
|
||||||
this._responses.set(request.requestId, {body, encodings});
|
this._responses.set(request.requestId, {body, encodings});
|
||||||
|
|||||||
@ -259,8 +259,8 @@ class PageHandler {
|
|||||||
this._pageNetwork.disableRequestInterception();
|
this._pageNetwork.disableRequestInterception();
|
||||||
}
|
}
|
||||||
|
|
||||||
async ['Network.resumeInterceptedRequest']({requestId, url, method, headers, postData, interceptResponse}) {
|
async ['Network.resumeInterceptedRequest']({requestId, url, method, headers, postData}) {
|
||||||
return await this._pageNetwork.resumeInterceptedRequest(requestId, url, method, headers, postData, interceptResponse);
|
this._pageNetwork.resumeInterceptedRequest(requestId, url, method, headers, postData);
|
||||||
}
|
}
|
||||||
|
|
||||||
async ['Network.abortInterceptedRequest']({requestId, errorCode}) {
|
async ['Network.abortInterceptedRequest']({requestId, errorCode}) {
|
||||||
|
|||||||
@ -205,12 +205,6 @@ networkTypes.ResourceTiming = {
|
|||||||
responseStart: t.Number,
|
responseStart: t.Number,
|
||||||
};
|
};
|
||||||
|
|
||||||
networkTypes.InterceptedResponse = {
|
|
||||||
status: t.Number,
|
|
||||||
statusText: t.String,
|
|
||||||
headers: t.Array(networkTypes.HTTPHeader),
|
|
||||||
};
|
|
||||||
|
|
||||||
const Browser = {
|
const Browser = {
|
||||||
targets: ['browser'],
|
targets: ['browser'],
|
||||||
|
|
||||||
@ -540,11 +534,6 @@ const Network = {
|
|||||||
method: t.Optional(t.String),
|
method: t.Optional(t.String),
|
||||||
headers: t.Optional(t.Array(networkTypes.HTTPHeader)),
|
headers: t.Optional(t.Array(networkTypes.HTTPHeader)),
|
||||||
postData: t.Optional(t.String),
|
postData: t.Optional(t.String),
|
||||||
interceptResponse: t.Optional(t.Boolean),
|
|
||||||
},
|
|
||||||
returns: {
|
|
||||||
response: t.Optional(networkTypes.InterceptedResponse),
|
|
||||||
error: t.Optional(t.String),
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
'fulfillInterceptedRequest': {
|
'fulfillInterceptedRequest': {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user