From 091c0065ad754bf57038c98f4ea5fce0020eefb6 Mon Sep 17 00:00:00 2001 From: Yury Semikhatsky Date: Thu, 4 Nov 2021 12:29:36 -0700 Subject: [PATCH] browser(firefox): delete response interception code (#10053) --- browser_patches/firefox-beta/BUILD_NUMBER | 4 +- .../firefox-beta/juggler/NetworkObserver.js | 255 ++---------------- .../juggler/protocol/PageHandler.js | 4 +- .../firefox-beta/juggler/protocol/Protocol.js | 11 - browser_patches/firefox/BUILD_NUMBER | 4 +- .../firefox/juggler/NetworkObserver.js | 255 ++---------------- .../firefox/juggler/protocol/PageHandler.js | 4 +- .../firefox/juggler/protocol/Protocol.js | 11 - 8 files changed, 62 insertions(+), 486 deletions(-) diff --git a/browser_patches/firefox-beta/BUILD_NUMBER b/browser_patches/firefox-beta/BUILD_NUMBER index 9e1a310b4e..e580183020 100644 --- a/browser_patches/firefox-beta/BUILD_NUMBER +++ b/browser_patches/firefox-beta/BUILD_NUMBER @@ -1,2 +1,2 @@ -1302 -Changed: yurys@chromium.org Mon 01 Nov 2021 05:04:30 PM PDT +1303 +Changed: yurys@chromium.org Thu 04 Nov 2021 12:26:04 PM PDT diff --git a/browser_patches/firefox-beta/juggler/NetworkObserver.js b/browser_patches/firefox-beta/juggler/NetworkObserver.js index 9efa8a1825..c2669ca852 100644 --- a/browser_patches/firefox-beta/juggler/NetworkObserver.js +++ b/browser_patches/firefox-beta/juggler/NetworkObserver.js @@ -73,15 +73,8 @@ class PageNetwork { this._interceptedRequests.clear(); } - async resumeInterceptedRequest(requestId, url, method, headers, postData, interceptResponse) { - 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); - } + resumeInterceptedRequest(requestId, url, method, headers, postData) { this._takeIntercepted(requestId).resume(url, method, headers, postData); - return {}; } 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 { constructor(networkObserver, httpChannel, redirectedFrom) { this._networkObserver = networkObserver; @@ -284,10 +132,6 @@ class NetworkRequest { // 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. redirectedFrom._sendOnRequestFinished(); - if (redirectedFrom._responseInterceptor) { - this._responseInterceptor = redirectedFrom._responseInterceptor; - this._responseInterceptor._finalRequest = this; - } } this._pageNetwork = redirectedFrom ? redirectedFrom._pageNetwork : networkObserver._findPageNetwork(httpChannel); @@ -305,10 +149,7 @@ class NetworkRequest { httpChannel.QueryInterface(Ci.nsITraceableChannel); this._originalListener = httpChannel.setNewListener(this); - // When fetching original response ResponseInterceptor creates a new HttpChannel - // 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)) { + if (redirectedFrom) { // Listener is inherited for regular redirects, so we'd like to avoid // calling into previous NetworkRequest. this._originalListener = redirectedFrom._originalListener; @@ -342,23 +183,12 @@ class NetworkRequest { // Public interception API. abort(errorCode) { const error = errorMap[errorCode] || Cr.NS_ERROR_FAILURE; - this._failWithErrorCode(error); - } - - _failWithErrorCode(error) { this._interceptedChannel.cancelInterception(error); this._interceptedChannel = undefined; } // Public interception API. 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); for (const header of headers) { 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); - synthesized.data = body; + synthesized.data = base64body ? atob(base64body) : ''; this._interceptedChannel.startSynthesizedResponse(synthesized, null, null, '', false); this._interceptedChannel.finishSynthesizedResponse(); this._interceptedChannel = undefined; @@ -598,12 +428,8 @@ class NetworkRequest { this._sendOnResponse(false); const body = this._responseBodyChunks.join(''); const pageNetwork = this._pageNetwork; - if (pageNetwork) { - if (this._responseInterceptor) - this._responseInterceptor.interceptAddResponseBody(this, body); - else - pageNetwork._responseStorage.addResponseBody(this, this.httpChannel, body); - } + if (pageNetwork) + pageNetwork._responseStorage.addResponseBody(this, body); this._sendOnRequestFinished(); } else { this._sendOnRequestFailed(aStatusCode); @@ -657,14 +483,6 @@ class NetworkRequest { } _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) { // We can come here twice because of internal redirects, e.g. service workers. return; @@ -674,32 +492,32 @@ class NetworkRequest { if (!pageNetwork) return; - httpChannel.QueryInterface(Ci.nsIHttpChannelInternal); - httpChannel.QueryInterface(Ci.nsITimedChannel); + this.httpChannel.QueryInterface(Ci.nsIHttpChannelInternal); + this.httpChannel.QueryInterface(Ci.nsITimedChannel); const timing = { - startTime: httpChannel.channelCreationTime, - domainLookupStart: httpChannel.domainLookupStartTime, - domainLookupEnd: httpChannel.domainLookupEndTime, - connectStart: httpChannel.connectStartTime, - secureConnectionStart: httpChannel.secureConnectionStartTime, - connectEnd: httpChannel.connectEndTime, - requestStart: httpChannel.requestStartTime, - responseStart: httpChannel.responseStartTime, + startTime: this.httpChannel.channelCreationTime, + domainLookupStart: this.httpChannel.domainLookupStartTime, + domainLookupEnd: this.httpChannel.domainLookupEndTime, + connectStart: this.httpChannel.connectStartTime, + secureConnectionStart: this.httpChannel.secureConnectionStartTime, + connectEnd: this.httpChannel.connectEndTime, + requestStart: this.httpChannel.requestStartTime, + 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 remotePort = undefined; try { - remoteIPAddress = httpChannel.remoteAddress; - remotePort = httpChannel.remotePort; + remoteIPAddress = this.httpChannel.remoteAddress; + remotePort = this.httpChannel.remotePort; } catch (e) { // remoteAddress is not defined for cached requests. } pageNetwork.emit(PageNetwork.Events.Response, { requestId: this.requestId, - securityDetails: getSecurityDetails(httpChannel), + securityDetails: getSecurityDetails(this.httpChannel), fromCache, headers, remoteIPAddress, @@ -711,14 +529,6 @@ class NetworkRequest { } _sendOnRequestFailed(error) { - if (this._responseInterceptor) { - this._responseInterceptor.interceptOnRequestFailed(error); - return; - } - this._sendOnRequestFailedImpl(error); - } - - _sendOnRequestFailedImpl(error) { const pageNetwork = this._pageNetwork; if (pageNetwork) { pageNetwork.emit(PageNetwork.Events.RequestFailed, { @@ -730,25 +540,17 @@ class NetworkRequest { } _sendOnRequestFinished() { - if (this._responseInterceptor) { - this._responseInterceptor.interceptOnRequestFinished(this); - return; - } - this._sendOnRequestFinishedImpl(this.httpChannel); - } - - _sendOnRequestFinishedImpl(httpChannel) { const pageNetwork = this._pageNetwork; if (pageNetwork) { pageNetwork.emit(PageNetwork.Events.RequestFinished, { requestId: this.requestId, - responseEndTime: httpChannel.responseEndTime, - transferSize: httpChannel.transferSize, - encodedBodySize: httpChannel.encodedBodySize, - protocolVersion: httpChannel.protocolVersion, + responseEndTime: this.httpChannel.responseEndTime, + transferSize: this.httpChannel.transferSize, + encodedBodySize: this.httpChannel.encodedBodySize, + protocolVersion: this.httpChannel.protocolVersion, }, 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._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(); this._channelProxyFilter = { @@ -854,8 +655,6 @@ class NetworkObserver { _onRequest(channel, topic) { if (!(channel instanceof Ci.nsIHttpChannel)) return; - if (this._responseInterceptionChannels.has(channel)) - return; const httpChannel = channel.QueryInterface(Ci.nsIHttpChannel); const channelId = httpChannel.channelId + ''; const redirectedFrom = this._expectedRedirect.get(channelId); @@ -982,7 +781,7 @@ class ResponseStorage { this._responses = new Map(); } - addResponseBody(request, httpChannel, body) { + addResponseBody(request, body) { if (body.length > this._maxResponseSize) { this._responses.set(request.requestId, { evicted: true, @@ -991,8 +790,8 @@ class ResponseStorage { return; } let encodings = []; - if ((httpChannel instanceof Ci.nsIEncodedChannel) && httpChannel.contentEncodings && !httpChannel.applyConversion) { - const encodingHeader = httpChannel.getResponseHeader("Content-Encoding"); + if ((request.httpChannel instanceof Ci.nsIEncodedChannel) && request.httpChannel.contentEncodings && !request.httpChannel.applyConversion) { + const encodingHeader = request.httpChannel.getResponseHeader("Content-Encoding"); encodings = encodingHeader.split(/\s*\t*,\s*\t*/); } this._responses.set(request.requestId, {body, encodings}); diff --git a/browser_patches/firefox-beta/juggler/protocol/PageHandler.js b/browser_patches/firefox-beta/juggler/protocol/PageHandler.js index 6eafe94c33..1f5e06a06d 100644 --- a/browser_patches/firefox-beta/juggler/protocol/PageHandler.js +++ b/browser_patches/firefox-beta/juggler/protocol/PageHandler.js @@ -259,8 +259,8 @@ class PageHandler { this._pageNetwork.disableRequestInterception(); } - async ['Network.resumeInterceptedRequest']({requestId, url, method, headers, postData, interceptResponse}) { - return await this._pageNetwork.resumeInterceptedRequest(requestId, url, method, headers, postData, interceptResponse); + async ['Network.resumeInterceptedRequest']({requestId, url, method, headers, postData}) { + this._pageNetwork.resumeInterceptedRequest(requestId, url, method, headers, postData); } async ['Network.abortInterceptedRequest']({requestId, errorCode}) { diff --git a/browser_patches/firefox-beta/juggler/protocol/Protocol.js b/browser_patches/firefox-beta/juggler/protocol/Protocol.js index 7302ca01fb..f2f99bc0b2 100644 --- a/browser_patches/firefox-beta/juggler/protocol/Protocol.js +++ b/browser_patches/firefox-beta/juggler/protocol/Protocol.js @@ -205,12 +205,6 @@ networkTypes.ResourceTiming = { responseStart: t.Number, }; -networkTypes.InterceptedResponse = { - status: t.Number, - statusText: t.String, - headers: t.Array(networkTypes.HTTPHeader), -}; - const Browser = { targets: ['browser'], @@ -540,11 +534,6 @@ const Network = { method: t.Optional(t.String), headers: t.Optional(t.Array(networkTypes.HTTPHeader)), postData: t.Optional(t.String), - interceptResponse: t.Optional(t.Boolean), - }, - returns: { - response: t.Optional(networkTypes.InterceptedResponse), - error: t.Optional(t.String), }, }, 'fulfillInterceptedRequest': { diff --git a/browser_patches/firefox/BUILD_NUMBER b/browser_patches/firefox/BUILD_NUMBER index 7e753a5628..9a44b88906 100644 --- a/browser_patches/firefox/BUILD_NUMBER +++ b/browser_patches/firefox/BUILD_NUMBER @@ -1,2 +1,2 @@ -1301 -Changed: lushnikov@chromium.org Thu Nov 4 08:24:38 HST 2021 +1302 +Changed: yurys@chromium.org Thu 04 Nov 2021 12:24:04 PM PDT diff --git a/browser_patches/firefox/juggler/NetworkObserver.js b/browser_patches/firefox/juggler/NetworkObserver.js index 9efa8a1825..c2669ca852 100644 --- a/browser_patches/firefox/juggler/NetworkObserver.js +++ b/browser_patches/firefox/juggler/NetworkObserver.js @@ -73,15 +73,8 @@ class PageNetwork { this._interceptedRequests.clear(); } - async resumeInterceptedRequest(requestId, url, method, headers, postData, interceptResponse) { - 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); - } + resumeInterceptedRequest(requestId, url, method, headers, postData) { this._takeIntercepted(requestId).resume(url, method, headers, postData); - return {}; } 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 { constructor(networkObserver, httpChannel, redirectedFrom) { this._networkObserver = networkObserver; @@ -284,10 +132,6 @@ class NetworkRequest { // 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. redirectedFrom._sendOnRequestFinished(); - if (redirectedFrom._responseInterceptor) { - this._responseInterceptor = redirectedFrom._responseInterceptor; - this._responseInterceptor._finalRequest = this; - } } this._pageNetwork = redirectedFrom ? redirectedFrom._pageNetwork : networkObserver._findPageNetwork(httpChannel); @@ -305,10 +149,7 @@ class NetworkRequest { httpChannel.QueryInterface(Ci.nsITraceableChannel); this._originalListener = httpChannel.setNewListener(this); - // When fetching original response ResponseInterceptor creates a new HttpChannel - // 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)) { + if (redirectedFrom) { // Listener is inherited for regular redirects, so we'd like to avoid // calling into previous NetworkRequest. this._originalListener = redirectedFrom._originalListener; @@ -342,23 +183,12 @@ class NetworkRequest { // Public interception API. abort(errorCode) { const error = errorMap[errorCode] || Cr.NS_ERROR_FAILURE; - this._failWithErrorCode(error); - } - - _failWithErrorCode(error) { this._interceptedChannel.cancelInterception(error); this._interceptedChannel = undefined; } // Public interception API. 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); for (const header of headers) { 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); - synthesized.data = body; + synthesized.data = base64body ? atob(base64body) : ''; this._interceptedChannel.startSynthesizedResponse(synthesized, null, null, '', false); this._interceptedChannel.finishSynthesizedResponse(); this._interceptedChannel = undefined; @@ -598,12 +428,8 @@ class NetworkRequest { this._sendOnResponse(false); const body = this._responseBodyChunks.join(''); const pageNetwork = this._pageNetwork; - if (pageNetwork) { - if (this._responseInterceptor) - this._responseInterceptor.interceptAddResponseBody(this, body); - else - pageNetwork._responseStorage.addResponseBody(this, this.httpChannel, body); - } + if (pageNetwork) + pageNetwork._responseStorage.addResponseBody(this, body); this._sendOnRequestFinished(); } else { this._sendOnRequestFailed(aStatusCode); @@ -657,14 +483,6 @@ class NetworkRequest { } _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) { // We can come here twice because of internal redirects, e.g. service workers. return; @@ -674,32 +492,32 @@ class NetworkRequest { if (!pageNetwork) return; - httpChannel.QueryInterface(Ci.nsIHttpChannelInternal); - httpChannel.QueryInterface(Ci.nsITimedChannel); + this.httpChannel.QueryInterface(Ci.nsIHttpChannelInternal); + this.httpChannel.QueryInterface(Ci.nsITimedChannel); const timing = { - startTime: httpChannel.channelCreationTime, - domainLookupStart: httpChannel.domainLookupStartTime, - domainLookupEnd: httpChannel.domainLookupEndTime, - connectStart: httpChannel.connectStartTime, - secureConnectionStart: httpChannel.secureConnectionStartTime, - connectEnd: httpChannel.connectEndTime, - requestStart: httpChannel.requestStartTime, - responseStart: httpChannel.responseStartTime, + startTime: this.httpChannel.channelCreationTime, + domainLookupStart: this.httpChannel.domainLookupStartTime, + domainLookupEnd: this.httpChannel.domainLookupEndTime, + connectStart: this.httpChannel.connectStartTime, + secureConnectionStart: this.httpChannel.secureConnectionStartTime, + connectEnd: this.httpChannel.connectEndTime, + requestStart: this.httpChannel.requestStartTime, + 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 remotePort = undefined; try { - remoteIPAddress = httpChannel.remoteAddress; - remotePort = httpChannel.remotePort; + remoteIPAddress = this.httpChannel.remoteAddress; + remotePort = this.httpChannel.remotePort; } catch (e) { // remoteAddress is not defined for cached requests. } pageNetwork.emit(PageNetwork.Events.Response, { requestId: this.requestId, - securityDetails: getSecurityDetails(httpChannel), + securityDetails: getSecurityDetails(this.httpChannel), fromCache, headers, remoteIPAddress, @@ -711,14 +529,6 @@ class NetworkRequest { } _sendOnRequestFailed(error) { - if (this._responseInterceptor) { - this._responseInterceptor.interceptOnRequestFailed(error); - return; - } - this._sendOnRequestFailedImpl(error); - } - - _sendOnRequestFailedImpl(error) { const pageNetwork = this._pageNetwork; if (pageNetwork) { pageNetwork.emit(PageNetwork.Events.RequestFailed, { @@ -730,25 +540,17 @@ class NetworkRequest { } _sendOnRequestFinished() { - if (this._responseInterceptor) { - this._responseInterceptor.interceptOnRequestFinished(this); - return; - } - this._sendOnRequestFinishedImpl(this.httpChannel); - } - - _sendOnRequestFinishedImpl(httpChannel) { const pageNetwork = this._pageNetwork; if (pageNetwork) { pageNetwork.emit(PageNetwork.Events.RequestFinished, { requestId: this.requestId, - responseEndTime: httpChannel.responseEndTime, - transferSize: httpChannel.transferSize, - encodedBodySize: httpChannel.encodedBodySize, - protocolVersion: httpChannel.protocolVersion, + responseEndTime: this.httpChannel.responseEndTime, + transferSize: this.httpChannel.transferSize, + encodedBodySize: this.httpChannel.encodedBodySize, + protocolVersion: this.httpChannel.protocolVersion, }, 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._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(); this._channelProxyFilter = { @@ -854,8 +655,6 @@ class NetworkObserver { _onRequest(channel, topic) { if (!(channel instanceof Ci.nsIHttpChannel)) return; - if (this._responseInterceptionChannels.has(channel)) - return; const httpChannel = channel.QueryInterface(Ci.nsIHttpChannel); const channelId = httpChannel.channelId + ''; const redirectedFrom = this._expectedRedirect.get(channelId); @@ -982,7 +781,7 @@ class ResponseStorage { this._responses = new Map(); } - addResponseBody(request, httpChannel, body) { + addResponseBody(request, body) { if (body.length > this._maxResponseSize) { this._responses.set(request.requestId, { evicted: true, @@ -991,8 +790,8 @@ class ResponseStorage { return; } let encodings = []; - if ((httpChannel instanceof Ci.nsIEncodedChannel) && httpChannel.contentEncodings && !httpChannel.applyConversion) { - const encodingHeader = httpChannel.getResponseHeader("Content-Encoding"); + if ((request.httpChannel instanceof Ci.nsIEncodedChannel) && request.httpChannel.contentEncodings && !request.httpChannel.applyConversion) { + const encodingHeader = request.httpChannel.getResponseHeader("Content-Encoding"); encodings = encodingHeader.split(/\s*\t*,\s*\t*/); } this._responses.set(request.requestId, {body, encodings}); diff --git a/browser_patches/firefox/juggler/protocol/PageHandler.js b/browser_patches/firefox/juggler/protocol/PageHandler.js index 6eafe94c33..1f5e06a06d 100644 --- a/browser_patches/firefox/juggler/protocol/PageHandler.js +++ b/browser_patches/firefox/juggler/protocol/PageHandler.js @@ -259,8 +259,8 @@ class PageHandler { this._pageNetwork.disableRequestInterception(); } - async ['Network.resumeInterceptedRequest']({requestId, url, method, headers, postData, interceptResponse}) { - return await this._pageNetwork.resumeInterceptedRequest(requestId, url, method, headers, postData, interceptResponse); + async ['Network.resumeInterceptedRequest']({requestId, url, method, headers, postData}) { + this._pageNetwork.resumeInterceptedRequest(requestId, url, method, headers, postData); } async ['Network.abortInterceptedRequest']({requestId, errorCode}) { diff --git a/browser_patches/firefox/juggler/protocol/Protocol.js b/browser_patches/firefox/juggler/protocol/Protocol.js index 7302ca01fb..f2f99bc0b2 100644 --- a/browser_patches/firefox/juggler/protocol/Protocol.js +++ b/browser_patches/firefox/juggler/protocol/Protocol.js @@ -205,12 +205,6 @@ networkTypes.ResourceTiming = { responseStart: t.Number, }; -networkTypes.InterceptedResponse = { - status: t.Number, - statusText: t.String, - headers: t.Array(networkTypes.HTTPHeader), -}; - const Browser = { targets: ['browser'], @@ -540,11 +534,6 @@ const Network = { method: t.Optional(t.String), headers: t.Optional(t.Array(networkTypes.HTTPHeader)), postData: t.Optional(t.String), - interceptResponse: t.Optional(t.Boolean), - }, - returns: { - response: t.Optional(networkTypes.InterceptedResponse), - error: t.Optional(t.String), }, }, 'fulfillInterceptedRequest': {