fix(chromium): race between requestPaused and requestWillBeSent in workers (#30125)
Workers use page's session for `Fetch` domain and worker's session for `Network` domain. Therefore, `CRNetworkManager` should keep track of the right session for each domain separately. This is covered by currently flaky tests: - `should report and intercept network from nested worker`, - `should intercept network activity from worker`, - `should intercept network activity from worker 2`.
This commit is contained in:
parent
dd1eca2a9d
commit
e4403dd6c8
|
|
@ -41,14 +41,14 @@ export class CRNetworkManager {
|
||||||
private _page: Page | null;
|
private _page: Page | null;
|
||||||
private _serviceWorker: CRServiceWorker | null;
|
private _serviceWorker: CRServiceWorker | null;
|
||||||
private _requestIdToRequest = new Map<string, InterceptableRequest>();
|
private _requestIdToRequest = new Map<string, InterceptableRequest>();
|
||||||
private _requestIdToRequestWillBeSentEvent = new Map<string, Protocol.Network.requestWillBeSentPayload>();
|
private _requestIdToRequestWillBeSentEvent = new Map<string, { sessionInfo: SessionInfo, event: Protocol.Network.requestWillBeSentPayload }>();
|
||||||
private _credentials: {origin?: string, username: string, password: string} | null = null;
|
private _credentials: {origin?: string, username: string, password: string} | null = null;
|
||||||
private _attemptedAuthentications = new Set<string>();
|
private _attemptedAuthentications = new Set<string>();
|
||||||
private _userRequestInterceptionEnabled = false;
|
private _userRequestInterceptionEnabled = false;
|
||||||
private _protocolRequestInterceptionEnabled = false;
|
private _protocolRequestInterceptionEnabled = false;
|
||||||
private _offline = false;
|
private _offline = false;
|
||||||
private _extraHTTPHeaders: types.HeadersArray = [];
|
private _extraHTTPHeaders: types.HeadersArray = [];
|
||||||
private _requestIdToRequestPausedEvent = new Map<string, Protocol.Fetch.requestPausedPayload>();
|
private _requestIdToRequestPausedEvent = new Map<string, { sessionInfo: SessionInfo, event: Protocol.Fetch.requestPausedPayload }>();
|
||||||
private _responseExtraInfoTracker = new ResponseExtraInfoTracker();
|
private _responseExtraInfoTracker = new ResponseExtraInfoTracker();
|
||||||
private _sessions = new Map<CRSession, SessionInfo>();
|
private _sessions = new Map<CRSession, SessionInfo>();
|
||||||
|
|
||||||
|
|
@ -195,13 +195,13 @@ export class CRNetworkManager {
|
||||||
const requestId = event.requestId;
|
const requestId = event.requestId;
|
||||||
const requestPausedEvent = this._requestIdToRequestPausedEvent.get(requestId);
|
const requestPausedEvent = this._requestIdToRequestPausedEvent.get(requestId);
|
||||||
if (requestPausedEvent) {
|
if (requestPausedEvent) {
|
||||||
this._onRequest(sessionInfo, event, requestPausedEvent);
|
this._onRequest(sessionInfo, event, requestPausedEvent.sessionInfo, requestPausedEvent.event);
|
||||||
this._requestIdToRequestPausedEvent.delete(requestId);
|
this._requestIdToRequestPausedEvent.delete(requestId);
|
||||||
} else {
|
} else {
|
||||||
this._requestIdToRequestWillBeSentEvent.set(event.requestId, event);
|
this._requestIdToRequestWillBeSentEvent.set(event.requestId, { sessionInfo, event });
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
this._onRequest(sessionInfo, event, null);
|
this._onRequest(sessionInfo, event, undefined, undefined);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -248,7 +248,7 @@ export class CRNetworkManager {
|
||||||
const requestId = event.networkId;
|
const requestId = event.networkId;
|
||||||
const requestWillBeSentEvent = this._requestIdToRequestWillBeSentEvent.get(requestId);
|
const requestWillBeSentEvent = this._requestIdToRequestWillBeSentEvent.get(requestId);
|
||||||
if (requestWillBeSentEvent) {
|
if (requestWillBeSentEvent) {
|
||||||
this._onRequest(sessionInfo, requestWillBeSentEvent, event);
|
this._onRequest(requestWillBeSentEvent.sessionInfo, requestWillBeSentEvent.event, sessionInfo, event);
|
||||||
this._requestIdToRequestWillBeSentEvent.delete(requestId);
|
this._requestIdToRequestWillBeSentEvent.delete(requestId);
|
||||||
} else {
|
} else {
|
||||||
const existingRequest = this._requestIdToRequest.get(requestId);
|
const existingRequest = this._requestIdToRequest.get(requestId);
|
||||||
|
|
@ -269,11 +269,11 @@ export class CRNetworkManager {
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this._requestIdToRequestPausedEvent.set(requestId, event);
|
this._requestIdToRequestPausedEvent.set(requestId, { sessionInfo, event });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_onRequest(sessionInfo: SessionInfo, requestWillBeSentEvent: Protocol.Network.requestWillBeSentPayload, requestPausedEvent: Protocol.Fetch.requestPausedPayload | null) {
|
_onRequest(requestWillBeSentSessionInfo: SessionInfo, requestWillBeSentEvent: Protocol.Network.requestWillBeSentPayload, requestPausedSessionInfo: SessionInfo | undefined, requestPausedEvent: Protocol.Fetch.requestPausedPayload | undefined) {
|
||||||
if (requestWillBeSentEvent.request.url.startsWith('data:'))
|
if (requestWillBeSentEvent.request.url.startsWith('data:'))
|
||||||
return;
|
return;
|
||||||
let redirectedFrom: InterceptableRequest | null = null;
|
let redirectedFrom: InterceptableRequest | null = null;
|
||||||
|
|
@ -285,7 +285,7 @@ export class CRNetworkManager {
|
||||||
redirectedFrom = request;
|
redirectedFrom = request;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let frame = requestWillBeSentEvent.frameId ? this._page?._frameManager.frame(requestWillBeSentEvent.frameId) : sessionInfo.workerFrame;
|
let frame = requestWillBeSentEvent.frameId ? this._page?._frameManager.frame(requestWillBeSentEvent.frameId) : requestWillBeSentSessionInfo.workerFrame;
|
||||||
// Requests from workers lack frameId, because we receive Network.requestWillBeSent
|
// Requests from workers lack frameId, because we receive Network.requestWillBeSent
|
||||||
// on the worker target. However, we receive Fetch.requestPaused on the page target,
|
// on the worker target. However, we receive Fetch.requestPaused on the page target,
|
||||||
// and lack workerFrame there. Luckily, Fetch.requestPaused provides a frameId.
|
// and lack workerFrame there. Luckily, Fetch.requestPaused provides a frameId.
|
||||||
|
|
@ -314,7 +314,7 @@ export class CRNetworkManager {
|
||||||
];
|
];
|
||||||
if (requestHeaders['Access-Control-Request-Headers'])
|
if (requestHeaders['Access-Control-Request-Headers'])
|
||||||
responseHeaders.push({ name: 'Access-Control-Allow-Headers', value: requestHeaders['Access-Control-Request-Headers'] });
|
responseHeaders.push({ name: 'Access-Control-Allow-Headers', value: requestHeaders['Access-Control-Request-Headers'] });
|
||||||
sessionInfo.session._sendMayFail('Fetch.fulfillRequest', {
|
requestPausedSessionInfo!.session._sendMayFail('Fetch.fulfillRequest', {
|
||||||
requestId: requestPausedEvent.requestId,
|
requestId: requestPausedEvent.requestId,
|
||||||
responseCode: 204,
|
responseCode: 204,
|
||||||
responsePhrase: network.STATUS_TEXTS['204'],
|
responsePhrase: network.STATUS_TEXTS['204'],
|
||||||
|
|
@ -327,7 +327,7 @@ export class CRNetworkManager {
|
||||||
// Non-service-worker requests MUST have a frame—if they don't, we pretend there was no request
|
// Non-service-worker requests MUST have a frame—if they don't, we pretend there was no request
|
||||||
if (!frame && !this._serviceWorker) {
|
if (!frame && !this._serviceWorker) {
|
||||||
if (requestPausedEvent)
|
if (requestPausedEvent)
|
||||||
sessionInfo.session._sendMayFail('Fetch.continueRequest', { requestId: requestPausedEvent.requestId });
|
requestPausedSessionInfo!.session._sendMayFail('Fetch.continueRequest', { requestId: requestPausedEvent.requestId });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -337,15 +337,15 @@ export class CRNetworkManager {
|
||||||
if (redirectedFrom || (!this._userRequestInterceptionEnabled && this._protocolRequestInterceptionEnabled)) {
|
if (redirectedFrom || (!this._userRequestInterceptionEnabled && this._protocolRequestInterceptionEnabled)) {
|
||||||
// Chromium does not preserve header overrides between redirects, so we have to do it ourselves.
|
// Chromium does not preserve header overrides between redirects, so we have to do it ourselves.
|
||||||
const headers = redirectedFrom?._originalRequestRoute?._alreadyContinuedParams?.headers;
|
const headers = redirectedFrom?._originalRequestRoute?._alreadyContinuedParams?.headers;
|
||||||
sessionInfo.session._sendMayFail('Fetch.continueRequest', { requestId: requestPausedEvent.requestId, headers });
|
requestPausedSessionInfo!.session._sendMayFail('Fetch.continueRequest', { requestId: requestPausedEvent.requestId, headers });
|
||||||
} else {
|
} else {
|
||||||
route = new RouteImpl(sessionInfo.session, requestPausedEvent.requestId);
|
route = new RouteImpl(requestPausedSessionInfo!.session, requestPausedEvent.requestId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const isNavigationRequest = requestWillBeSentEvent.requestId === requestWillBeSentEvent.loaderId && requestWillBeSentEvent.type === 'Document';
|
const isNavigationRequest = requestWillBeSentEvent.requestId === requestWillBeSentEvent.loaderId && requestWillBeSentEvent.type === 'Document';
|
||||||
const documentId = isNavigationRequest ? requestWillBeSentEvent.loaderId : undefined;
|
const documentId = isNavigationRequest ? requestWillBeSentEvent.loaderId : undefined;
|
||||||
const request = new InterceptableRequest({
|
const request = new InterceptableRequest({
|
||||||
session: sessionInfo.session,
|
session: requestWillBeSentSessionInfo.session,
|
||||||
context: (this._page || this._serviceWorker)!._browserContext,
|
context: (this._page || this._serviceWorker)!._browserContext,
|
||||||
frame: frame || null,
|
frame: frame || null,
|
||||||
serviceWorker: this._serviceWorker || null,
|
serviceWorker: this._serviceWorker || null,
|
||||||
|
|
@ -463,7 +463,7 @@ export class CRNetworkManager {
|
||||||
const requestWillBeSentEvent = this._requestIdToRequestWillBeSentEvent.get(event.requestId);
|
const requestWillBeSentEvent = this._requestIdToRequestWillBeSentEvent.get(event.requestId);
|
||||||
if (requestWillBeSentEvent) {
|
if (requestWillBeSentEvent) {
|
||||||
this._requestIdToRequestWillBeSentEvent.delete(event.requestId);
|
this._requestIdToRequestWillBeSentEvent.delete(event.requestId);
|
||||||
this._onRequest(sessionInfo, requestWillBeSentEvent, null /* requestPausedPayload */);
|
this._onRequest(sessionInfo, requestWillBeSentEvent.event, undefined, undefined);
|
||||||
request = this._requestIdToRequest.get(event.requestId);
|
request = this._requestIdToRequest.get(event.requestId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -508,7 +508,7 @@ export class CRNetworkManager {
|
||||||
// We stop waiting for Fetch.requestPaused (it might never come), and dispatch request event
|
// We stop waiting for Fetch.requestPaused (it might never come), and dispatch request event
|
||||||
// right away, followed by requestfailed event.
|
// right away, followed by requestfailed event.
|
||||||
this._requestIdToRequestWillBeSentEvent.delete(event.requestId);
|
this._requestIdToRequestWillBeSentEvent.delete(event.requestId);
|
||||||
this._onRequest(sessionInfo, requestWillBeSentEvent, null);
|
this._onRequest(sessionInfo, requestWillBeSentEvent.event, undefined, undefined);
|
||||||
request = this._requestIdToRequest.get(event.requestId);
|
request = this._requestIdToRequest.get(event.requestId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -544,7 +544,7 @@ export class CRNetworkManager {
|
||||||
class InterceptableRequest {
|
class InterceptableRequest {
|
||||||
readonly request: network.Request;
|
readonly request: network.Request;
|
||||||
readonly _requestId: string;
|
readonly _requestId: string;
|
||||||
readonly _interceptionId: string | null;
|
readonly _interceptionId: string | undefined;
|
||||||
readonly _documentId: string | undefined;
|
readonly _documentId: string | undefined;
|
||||||
readonly _timestamp: number;
|
readonly _timestamp: number;
|
||||||
readonly _wallTime: number;
|
readonly _wallTime: number;
|
||||||
|
|
@ -562,7 +562,7 @@ class InterceptableRequest {
|
||||||
documentId?: string;
|
documentId?: string;
|
||||||
route: RouteImpl | null;
|
route: RouteImpl | null;
|
||||||
requestWillBeSentEvent: Protocol.Network.requestWillBeSentPayload;
|
requestWillBeSentEvent: Protocol.Network.requestWillBeSentPayload;
|
||||||
requestPausedEvent: Protocol.Fetch.requestPausedPayload | null;
|
requestPausedEvent: Protocol.Fetch.requestPausedPayload | undefined;
|
||||||
redirectedFrom: InterceptableRequest | null;
|
redirectedFrom: InterceptableRequest | null;
|
||||||
}) {
|
}) {
|
||||||
const { session, context, frame, documentId, route, requestWillBeSentEvent, requestPausedEvent, redirectedFrom, serviceWorker } = options;
|
const { session, context, frame, documentId, route, requestWillBeSentEvent, requestPausedEvent, redirectedFrom, serviceWorker } = options;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue