browser(firefox): failure response interception (#8194)

This commit is contained in:
Yury Semikhatsky 2021-08-16 09:36:28 -07:00 committed by GitHub
parent f4c8fa3c56
commit 90385a7941
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 82 additions and 50 deletions

View file

@ -1,2 +1,2 @@
1278 1279
Changed: lushnikov@chromium.org Fri 13 Aug 2021 08:38:35 AM PDT Changed: yurys@chromium.org Fri 13 Aug 2021 07:00:48 PM PDT

View file

@ -78,7 +78,7 @@ class PageNetwork {
const intercepted = this._interceptedRequests.get(requestId); const intercepted = this._interceptedRequests.get(requestId);
if (!intercepted) if (!intercepted)
throw new Error(`Cannot find request "${requestId}"`); throw new Error(`Cannot find request "${requestId}"`);
return { response: await new ResponseInterceptor(intercepted).interceptResponse(url, method, headers, postData) }; 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 {}; return {};
@ -152,37 +152,47 @@ class ResponseInterceptor {
// channel gets redirected we report the redirect on the original(paused) // channel gets redirected we report the redirect on the original(paused)
// request. // request.
networkObserver._channelToRequest.set(newChannel, this._originalRequest); networkObserver._channelToRequest.set(newChannel, this._originalRequest);
const body = await new Promise((resolve, reject) => { const pageNetwork = this._originalRequest._pageNetwork;
NetUtil.asyncFetch(newChannel, (stream, status) => { let body;
networkObserver._responseInterceptionChannels.delete(newChannel); try {
networkObserver._channelToRequest.delete(newChannel); body = await new Promise((resolve, reject) => {
if (!Components.isSuccessCode(status)) { NetUtil.asyncFetch(newChannel, (stream, status) => {
reject(status); networkObserver._responseInterceptionChannels.delete(newChannel);
return; networkObserver._channelToRequest.delete(newChannel);
} if (!Components.isSuccessCode(status)) {
try { reject(status);
resolve(NetUtil.readInputStreamToString(stream, stream.available())); return;
} catch (e) {
if (e.result == Cr.NS_BASE_STREAM_CLOSED) {
// The stream was empty.
resolve('');
} else {
reject(e);
} }
} finally { try {
stream.close(); 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 finalRequest = this._finalRequest;
const responseChannel = finalRequest === this._originalRequest ? this._responseChannel : finalRequest.httpChannel; const responseChannel = finalRequest === this._originalRequest ? this._responseChannel : finalRequest.httpChannel;
const pageNetwork = this._originalRequest._pageNetwork;
if (pageNetwork) if (pageNetwork)
pageNetwork._responseStorage.addResponseBody(finalRequest, responseChannel, body); pageNetwork._responseStorage.addResponseBody(finalRequest, responseChannel, body);
const response = responseHead(responseChannel); const response = responseHead(responseChannel);
this._interceptedResponse = Object.assign({ body }, response); this._interceptedResponse = Object.assign({ body }, response);
return response; return { response };
} }
isInterceptedRequest(request) { isInterceptedRequest(request) {
@ -332,6 +342,10 @@ 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;
} }

View file

@ -536,6 +536,7 @@ const Network = {
}, },
returns: { returns: {
response: t.Optional(networkTypes.InterceptedResponse), response: t.Optional(networkTypes.InterceptedResponse),
error: t.Optional(t.String),
}, },
}, },
'fulfillInterceptedRequest': { 'fulfillInterceptedRequest': {

View file

@ -1,2 +1,2 @@
1283 1284
Changed: dgozman@gmail.com Thu Aug 12 16:33:32 PDT 2021 Changed: yurys@chromium.org Fri 13 Aug 2021 07:00:24 PM PDT

View file

@ -78,7 +78,7 @@ class PageNetwork {
const intercepted = this._interceptedRequests.get(requestId); const intercepted = this._interceptedRequests.get(requestId);
if (!intercepted) if (!intercepted)
throw new Error(`Cannot find request "${requestId}"`); throw new Error(`Cannot find request "${requestId}"`);
return { response: await new ResponseInterceptor(intercepted).interceptResponse(url, method, headers, postData) }; 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 {}; return {};
@ -152,37 +152,47 @@ class ResponseInterceptor {
// channel gets redirected we report the redirect on the original(paused) // channel gets redirected we report the redirect on the original(paused)
// request. // request.
networkObserver._channelToRequest.set(newChannel, this._originalRequest); networkObserver._channelToRequest.set(newChannel, this._originalRequest);
const body = await new Promise((resolve, reject) => { const pageNetwork = this._originalRequest._pageNetwork;
NetUtil.asyncFetch(newChannel, (stream, status) => { let body;
networkObserver._responseInterceptionChannels.delete(newChannel); try {
networkObserver._channelToRequest.delete(newChannel); body = await new Promise((resolve, reject) => {
if (!Components.isSuccessCode(status)) { NetUtil.asyncFetch(newChannel, (stream, status) => {
reject(status); networkObserver._responseInterceptionChannels.delete(newChannel);
return; networkObserver._channelToRequest.delete(newChannel);
} if (!Components.isSuccessCode(status)) {
try { reject(status);
resolve(NetUtil.readInputStreamToString(stream, stream.available())); return;
} catch (e) {
if (e.result == Cr.NS_BASE_STREAM_CLOSED) {
// The stream was empty.
resolve('');
} else {
reject(e);
} }
} finally { try {
stream.close(); 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 finalRequest = this._finalRequest;
const responseChannel = finalRequest === this._originalRequest ? this._responseChannel : finalRequest.httpChannel; const responseChannel = finalRequest === this._originalRequest ? this._responseChannel : finalRequest.httpChannel;
const pageNetwork = this._originalRequest._pageNetwork;
if (pageNetwork) if (pageNetwork)
pageNetwork._responseStorage.addResponseBody(finalRequest, responseChannel, body); pageNetwork._responseStorage.addResponseBody(finalRequest, responseChannel, body);
const response = responseHead(responseChannel); const response = responseHead(responseChannel);
this._interceptedResponse = Object.assign({ body }, response); this._interceptedResponse = Object.assign({ body }, response);
return response; return { response };
} }
isInterceptedRequest(request) { isInterceptedRequest(request) {
@ -332,6 +342,10 @@ 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;
} }

View file

@ -536,6 +536,7 @@ const Network = {
}, },
returns: { returns: {
response: t.Optional(networkTypes.InterceptedResponse), response: t.Optional(networkTypes.InterceptedResponse),
error: t.Optional(t.String),
}, },
}, },
'fulfillInterceptedRequest': { 'fulfillInterceptedRequest': {

View file

@ -227,6 +227,8 @@ class FFRouteImpl implements network.RouteDelegate {
}) as any; }) as any;
if (!overrides.interceptResponse) if (!overrides.interceptResponse)
return null; return null;
if (result.error)
throw new Error(`Request failed: ${result.error}`);
return new InterceptedResponse(request, result.response.status, result.response.statusText, result.response.headers); return new InterceptedResponse(request, result.response.status, result.response.statusText, result.response.headers);
} }