fix(requestinterception): fix font loading issue (#7060)
See https://github.com/puppeteer/puppeteer/pull/6996#issuecomment-811546501 and https://github.com/puppeteer/puppeteer/pull/6996#issuecomment-813797393 for context. Issue: #7038
This commit is contained in:
parent
8126101980
commit
c9978d20d5
@ -69,11 +69,47 @@ export class NetworkManager extends EventEmitter {
|
|||||||
_client: CDPSession;
|
_client: CDPSession;
|
||||||
_ignoreHTTPSErrors: boolean;
|
_ignoreHTTPSErrors: boolean;
|
||||||
_frameManager: FrameManager;
|
_frameManager: FrameManager;
|
||||||
_requestIdToRequest = new Map<string, HTTPRequest>();
|
|
||||||
|
/*
|
||||||
|
* There are four possible orders of events:
|
||||||
|
* A. `_onRequestWillBeSent`
|
||||||
|
* B. `_onRequestWillBeSent`, `_onRequestPaused`
|
||||||
|
* C. `_onRequestPaused`, `_onRequestWillBeSent`
|
||||||
|
* D. `_onRequestPaused`, `_onRequestWillBeSent`, `_onRequestPaused`
|
||||||
|
* (see crbug.com/1196004)
|
||||||
|
*
|
||||||
|
* For `_onRequest` we need the event from `_onRequestWillBeSent` and
|
||||||
|
* optionally the `interceptionId` from `_onRequestPaused`.
|
||||||
|
*
|
||||||
|
* If request interception is disabled, call `_onRequest` once per call to
|
||||||
|
* `_onRequestWillBeSent`.
|
||||||
|
* If request interception is enabled, call `_onRequest` once per call to
|
||||||
|
* `_onRequestPaused` (once per `interceptionId`).
|
||||||
|
*
|
||||||
|
* Events are stored to allow for subsequent events to call `_onRequest`.
|
||||||
|
*
|
||||||
|
* Note that (chains of) redirect requests have the same `requestId` (!) as
|
||||||
|
* the original request. We have to anticipate series of events like these:
|
||||||
|
* A. `_onRequestWillBeSent`,
|
||||||
|
* `_onRequestWillBeSent`, ...
|
||||||
|
* B. `_onRequestWillBeSent`, `_onRequestPaused`,
|
||||||
|
* `_onRequestWillBeSent`, `_onRequestPaused`, ...
|
||||||
|
* C. `_onRequestWillBeSent`, `_onRequestPaused`,
|
||||||
|
* `_onRequestPaused`, `_onRequestWillBeSent`, ...
|
||||||
|
* D. `_onRequestPaused`, `_onRequestWillBeSent`,
|
||||||
|
* `_onRequestPaused`, `_onRequestWillBeSent`, `_onRequestPaused`, ...
|
||||||
|
* (see crbug.com/1196004)
|
||||||
|
*/
|
||||||
_requestIdToRequestWillBeSentEvent = new Map<
|
_requestIdToRequestWillBeSentEvent = new Map<
|
||||||
string,
|
string,
|
||||||
Protocol.Network.RequestWillBeSentEvent
|
Protocol.Network.RequestWillBeSentEvent
|
||||||
>();
|
>();
|
||||||
|
_requestIdToRequestPausedEvent = new Map<
|
||||||
|
string,
|
||||||
|
Protocol.Fetch.RequestPausedEvent
|
||||||
|
>();
|
||||||
|
_requestIdToRequest = new Map<string, HTTPRequest>();
|
||||||
|
|
||||||
_extraHTTPHeaders: Record<string, string> = {};
|
_extraHTTPHeaders: Record<string, string> = {};
|
||||||
_credentials?: Credentials = null;
|
_credentials?: Credentials = null;
|
||||||
_attemptedAuthentications = new Set<string>();
|
_attemptedAuthentications = new Set<string>();
|
||||||
@ -81,7 +117,6 @@ export class NetworkManager extends EventEmitter {
|
|||||||
_userRequestInterceptionCacheSafe = false;
|
_userRequestInterceptionCacheSafe = false;
|
||||||
_protocolRequestInterceptionEnabled = false;
|
_protocolRequestInterceptionEnabled = false;
|
||||||
_userCacheDisabled = false;
|
_userCacheDisabled = false;
|
||||||
_requestIdToInterceptionId = new Map<string, string>();
|
|
||||||
_emulatedNetworkConditions: InternalNetworkConditions = {
|
_emulatedNetworkConditions: InternalNetworkConditions = {
|
||||||
offline: false,
|
offline: false,
|
||||||
upload: -1,
|
upload: -1,
|
||||||
@ -222,12 +257,17 @@ export class NetworkManager extends EventEmitter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_cacheDisabled(): boolean {
|
||||||
|
return (
|
||||||
|
this._userCacheDisabled ||
|
||||||
|
(this._userRequestInterceptionEnabled &&
|
||||||
|
!this._userRequestInterceptionCacheSafe)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
async _updateProtocolCacheDisabled(): Promise<void> {
|
async _updateProtocolCacheDisabled(): Promise<void> {
|
||||||
await this._client.send('Network.setCacheDisabled', {
|
await this._client.send('Network.setCacheDisabled', {
|
||||||
cacheDisabled:
|
cacheDisabled: this._cacheDisabled(),
|
||||||
this._userCacheDisabled ||
|
|
||||||
(this._userRequestInterceptionEnabled &&
|
|
||||||
!this._userRequestInterceptionCacheSafe),
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -238,13 +278,18 @@ export class NetworkManager extends EventEmitter {
|
|||||||
!event.request.url.startsWith('data:')
|
!event.request.url.startsWith('data:')
|
||||||
) {
|
) {
|
||||||
const requestId = event.requestId;
|
const requestId = event.requestId;
|
||||||
const interceptionId = this._requestIdToInterceptionId.get(requestId);
|
const requestPausedEvent = this._requestIdToRequestPausedEvent.get(
|
||||||
if (interceptionId) {
|
requestId
|
||||||
|
);
|
||||||
|
|
||||||
|
this._requestIdToRequestWillBeSentEvent.set(requestId, event);
|
||||||
|
|
||||||
|
if (requestPausedEvent) {
|
||||||
|
const interceptionId = requestPausedEvent.requestId;
|
||||||
this._onRequest(event, interceptionId);
|
this._onRequest(event, interceptionId);
|
||||||
this._requestIdToInterceptionId.delete(requestId);
|
this._requestIdToRequestPausedEvent.delete(requestId);
|
||||||
} else {
|
|
||||||
this._requestIdToRequestWillBeSentEvent.set(event.requestId, event);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this._onRequest(event, null);
|
this._onRequest(event, null);
|
||||||
@ -288,14 +333,30 @@ export class NetworkManager extends EventEmitter {
|
|||||||
|
|
||||||
const requestId = event.networkId;
|
const requestId = event.networkId;
|
||||||
const interceptionId = event.requestId;
|
const interceptionId = event.requestId;
|
||||||
if (requestId && this._requestIdToRequestWillBeSentEvent.has(requestId)) {
|
|
||||||
const requestWillBeSentEvent = this._requestIdToRequestWillBeSentEvent.get(
|
if (!requestId) {
|
||||||
requestId
|
return;
|
||||||
);
|
}
|
||||||
|
|
||||||
|
let requestWillBeSentEvent = this._requestIdToRequestWillBeSentEvent.get(
|
||||||
|
requestId
|
||||||
|
);
|
||||||
|
|
||||||
|
// redirect requests have the same `requestId`,
|
||||||
|
if (
|
||||||
|
requestWillBeSentEvent &&
|
||||||
|
(requestWillBeSentEvent.request.url !== event.request.url ||
|
||||||
|
requestWillBeSentEvent.request.method !== event.request.method)
|
||||||
|
) {
|
||||||
|
this._requestIdToRequestWillBeSentEvent.delete(requestId);
|
||||||
|
requestWillBeSentEvent = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (requestWillBeSentEvent) {
|
||||||
this._onRequest(requestWillBeSentEvent, interceptionId);
|
this._onRequest(requestWillBeSentEvent, interceptionId);
|
||||||
this._requestIdToRequestWillBeSentEvent.delete(requestId);
|
this._requestIdToRequestWillBeSentEvent.delete(requestId);
|
||||||
} else {
|
} else {
|
||||||
this._requestIdToInterceptionId.set(requestId, interceptionId);
|
this._requestIdToRequestPausedEvent.set(requestId, event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -346,8 +407,7 @@ export class NetworkManager extends EventEmitter {
|
|||||||
response._resolveBody(
|
response._resolveBody(
|
||||||
new Error('Response body is unavailable for redirect responses')
|
new Error('Response body is unavailable for redirect responses')
|
||||||
);
|
);
|
||||||
this._requestIdToRequest.delete(request._requestId);
|
this._forgetRequest(request, false);
|
||||||
this._attemptedAuthentications.delete(request._interceptionId);
|
|
||||||
this.emit(NetworkManagerEmittedEvents.Response, response);
|
this.emit(NetworkManagerEmittedEvents.Response, response);
|
||||||
this.emit(NetworkManagerEmittedEvents.RequestFinished, request);
|
this.emit(NetworkManagerEmittedEvents.RequestFinished, request);
|
||||||
}
|
}
|
||||||
@ -361,6 +421,19 @@ export class NetworkManager extends EventEmitter {
|
|||||||
this.emit(NetworkManagerEmittedEvents.Response, response);
|
this.emit(NetworkManagerEmittedEvents.Response, response);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_forgetRequest(request: HTTPRequest, events: boolean): void {
|
||||||
|
const requestId = request._requestId;
|
||||||
|
const interceptionId = request._interceptionId;
|
||||||
|
|
||||||
|
this._requestIdToRequest.delete(requestId);
|
||||||
|
this._attemptedAuthentications.delete(interceptionId);
|
||||||
|
|
||||||
|
if (events) {
|
||||||
|
this._requestIdToRequestWillBeSentEvent.delete(requestId);
|
||||||
|
this._requestIdToRequestPausedEvent.delete(requestId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
_onLoadingFinished(event: Protocol.Network.LoadingFinishedEvent): void {
|
_onLoadingFinished(event: Protocol.Network.LoadingFinishedEvent): void {
|
||||||
const request = this._requestIdToRequest.get(event.requestId);
|
const request = this._requestIdToRequest.get(event.requestId);
|
||||||
// For certain requestIds we never receive requestWillBeSent event.
|
// For certain requestIds we never receive requestWillBeSent event.
|
||||||
@ -370,8 +443,7 @@ export class NetworkManager extends EventEmitter {
|
|||||||
// Under certain conditions we never get the Network.responseReceived
|
// Under certain conditions we never get the Network.responseReceived
|
||||||
// event from protocol. @see https://crbug.com/883475
|
// event from protocol. @see https://crbug.com/883475
|
||||||
if (request.response()) request.response()._resolveBody(null);
|
if (request.response()) request.response()._resolveBody(null);
|
||||||
this._requestIdToRequest.delete(request._requestId);
|
this._forgetRequest(request, true);
|
||||||
this._attemptedAuthentications.delete(request._interceptionId);
|
|
||||||
this.emit(NetworkManagerEmittedEvents.RequestFinished, request);
|
this.emit(NetworkManagerEmittedEvents.RequestFinished, request);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -383,8 +455,7 @@ export class NetworkManager extends EventEmitter {
|
|||||||
request._failureText = event.errorText;
|
request._failureText = event.errorText;
|
||||||
const response = request.response();
|
const response = request.response();
|
||||||
if (response) response._resolveBody(null);
|
if (response) response._resolveBody(null);
|
||||||
this._requestIdToRequest.delete(request._requestId);
|
this._forgetRequest(request, true);
|
||||||
this._attemptedAuthentications.delete(request._interceptionId);
|
|
||||||
this.emit(NetworkManagerEmittedEvents.RequestFailed, request);
|
this.emit(NetworkManagerEmittedEvents.RequestFailed, request);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
9
test/assets/cached/one-style-font.css
Normal file
9
test/assets/cached/one-style-font.css
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
@font-face {
|
||||||
|
font-family: 'one-style';
|
||||||
|
src: url('./one-style.woff') format('woff');
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
background-color: pink;
|
||||||
|
font-family: 'one-style', sans-serif;
|
||||||
|
}
|
2
test/assets/cached/one-style-font.html
Normal file
2
test/assets/cached/one-style-font.html
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
<link rel='stylesheet' href='./one-style-font.css'>
|
||||||
|
<div>hello, world!</div>
|
@ -525,6 +525,15 @@ describe('request interception', function () {
|
|||||||
await page.reload();
|
await page.reload();
|
||||||
expect(cached.length).toBe(1);
|
expect(cached.length).toBe(1);
|
||||||
});
|
});
|
||||||
|
it('should load fonts if cache-safe', async () => {
|
||||||
|
const { page, server } = getTestState();
|
||||||
|
|
||||||
|
await page.setRequestInterception(true, true);
|
||||||
|
page.on('request', (request) => request.continue());
|
||||||
|
|
||||||
|
await page.goto(server.PREFIX + '/cached/one-style-font.html');
|
||||||
|
await page.waitForResponse((r) => r.url().endsWith('/one-style.woff'));
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describeFailsFirefox('Request.continue', function () {
|
describeFailsFirefox('Request.continue', function () {
|
||||||
|
Loading…
Reference in New Issue
Block a user