Skip to content

Commit 0dd2bb9

Browse files
authored
fix(har): WebSocket message timestamps should be in milliseconds (#41364)
the `timestamp` should also be multipled by 1000 just like the `walltime` fixes <#41360>
1 parent 2a2743f commit 0dd2bb9

4 files changed

Lines changed: 32 additions & 14 deletions

File tree

‎packages/playwright-core/src/server/chromium/crNetworkManager.ts‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -549,7 +549,7 @@ export class CRNetworkManager {
549549

550550
_onWebSocketWillSendHandshakeRequest(event: Protocol.Network.webSocketWillSendHandshakeRequestPayload) {
551551
const wallTimeMs = event.wallTime * 1000;
552-
this._timestampBaselineForWebSocket.set(event.requestId, wallTimeMs - event.timestamp);
552+
this._timestampBaselineForWebSocket.set(event.requestId, wallTimeMs - event.timestamp * 1000);
553553
this._page!.frameManager.onWebSocketRequest(event.requestId, headersObjectToArray(event.request.headers, '\n'), wallTimeMs);
554554
}
555555

@@ -559,7 +559,7 @@ export class CRNetworkManager {
559559
}
560560

561561
_timestampToWallTimeMsForWebSocket(requestId: string, timestamp: number): number {
562-
return this._timestampBaselineForWebSocket.get(requestId)! + timestamp;
562+
return this._timestampBaselineForWebSocket.get(requestId)! + timestamp * 1000;
563563
}
564564

565565
private _maybeUpdateRequestSession(sessionInfo: SessionInfo, request: InterceptableRequest) {

‎packages/playwright-core/src/server/webkit/webview/wvPage.ts‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1016,7 +1016,7 @@ export class WVPage implements PageDelegate {
10161016

10171017
_onWebSocketWillSendHandshakeRequest(event: Protocol.Network.webSocketWillSendHandshakeRequestPayload) {
10181018
const wallTimeMs = event.walltime * 1000;
1019-
this._timestampBaselineForWebSocket.set(event.requestId, wallTimeMs - event.timestamp);
1019+
this._timestampBaselineForWebSocket.set(event.requestId, wallTimeMs - event.timestamp * 1000);
10201020
this._page.frameManager.onWebSocketRequest(event.requestId, headersObjectToArray(event.request.headers), wallTimeMs);
10211021
}
10221022

@@ -1026,7 +1026,7 @@ export class WVPage implements PageDelegate {
10261026
}
10271027

10281028
_timestampToWallTimeMsForWebSocket(requestId: string, timestamp: number): number {
1029-
return this._timestampBaselineForWebSocket.get(requestId)! + timestamp;
1029+
return this._timestampBaselineForWebSocket.get(requestId)! + timestamp * 1000;
10301030
}
10311031

10321032
shouldToggleStyleSheetToSyncAnimations(): boolean {

‎packages/playwright-core/src/server/webkit/wkPage.ts‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1209,7 +1209,7 @@ export class WKPage implements PageDelegate {
12091209

12101210
_onWebSocketWillSendHandshakeRequest(event: Protocol.Network.webSocketWillSendHandshakeRequestPayload) {
12111211
const wallTimeMs = event.walltime * 1000;
1212-
this._timestampBaselineForWebSocket.set(event.requestId, wallTimeMs - event.timestamp);
1212+
this._timestampBaselineForWebSocket.set(event.requestId, wallTimeMs - event.timestamp * 1000);
12131213
this._page.frameManager.onWebSocketRequest(event.requestId, headersObjectToArray(event.request.headers), wallTimeMs);
12141214
}
12151215

@@ -1219,7 +1219,7 @@ export class WKPage implements PageDelegate {
12191219
}
12201220

12211221
_timestampToWallTimeMsForWebSocket(requestId: string, timestamp: number): number {
1222-
return this._timestampBaselineForWebSocket.get(requestId)! + timestamp;
1222+
return this._timestampBaselineForWebSocket.get(requestId)! + timestamp * 1000;
12231223
}
12241224

12251225
async _grantPermissions(origin: string, permissions: string[]) {

‎tests/library/har-websocket.spec.ts‎

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ it('should include websocket handshake headers and status', async ({ contextFact
100100
const { page, getLog } = await pageWithHar(contextFactory, testInfo);
101101
await page.goto(server.EMPTY_PAGE);
102102

103+
const beforeMs = Date.now();
103104
const wsUrl = `ws://${server.HOST}/ws`;
104105
const closed = page.evaluate(url => new Promise<void>(resolve => {
105106
const ws = new WebSocket(url);
@@ -108,6 +109,7 @@ it('should include websocket handshake headers and status', async ({ contextFact
108109
}), wsUrl);
109110
await closed;
110111
const log = await getLog();
112+
const afterMs = Date.now();
111113

112114
const wsEntry = log.entries.find(e => e.request.url === wsUrl)! as Entry;
113115
expect(wsEntry._resourceType).toBe('websocket');
@@ -116,6 +118,10 @@ it('should include websocket handshake headers and status', async ({ contextFact
116118
expect(wsEntry.response.statusText).toBe('Switching Protocols');
117119
expect(wsEntry.response.headersSize).toBe(responseHeadersSize(wsEntry.response.headers));
118120

121+
const wallTimeMs = new Date(wsEntry.startedDateTime).getTime();
122+
expect(wallTimeMs).toBeGreaterThanOrEqual(beforeMs);
123+
expect(wallTimeMs).toBeLessThanOrEqual(afterMs);
124+
119125
const requestHeaderNames = wsEntry.request.headers.map(h => h.name.toLowerCase());
120126
expect(requestHeaderNames).toContain('upgrade');
121127
expect(requestHeaderNames).toContain('connection');
@@ -135,12 +141,19 @@ async function testWebSocketMessages(contextFactory, server, testInfo, content,
135141
const incomingBinary = [(new Array(125)).fill(0x01), (new Array(126)).fill(0x01), (new Array(2 ** 16)).fill(0x01)];
136142
const outgoingText = ['y'.repeat(125), 'y'.repeat(126), 'y'.repeat(2 ** 16)];
137143
const outgoingBinary = [(new Array(125)).fill(0x02), (new Array(126)).fill(0x02), (new Array(2 ** 16)).fill(0x02)];
144+
const incomingCount = incomingText.length + incomingBinary.length;
145+
const outgoingCount = outgoingText.length + outgoingBinary.length;
146+
const delayMs = 100;
138147

139-
server.onceWebSocketConnection(ws => {
140-
for (const text of incomingText)
148+
server.onceWebSocketConnection(async ws => {
149+
for (const text of incomingText) {
141150
ws.send(text);
142-
for (const binary of incomingBinary)
151+
await new Promise(resolve => setTimeout(resolve, delayMs));
152+
}
153+
for (const binary of incomingBinary) {
154+
await new Promise(resolve => setTimeout(resolve, delayMs));
143155
ws.send(Buffer.from(binary));
156+
}
144157
});
145158

146159
const outputPath = content === 'embed' ? undefined : 'test.har.zip';
@@ -149,20 +162,24 @@ async function testWebSocketMessages(contextFactory, server, testInfo, content,
149162

150163
const beforeMs = Date.now();
151164
const wsUrl = `ws://${server.HOST}/ws`;
152-
const closed = page.evaluate(({ url, incomingCount, outgoingText, outgoingBinary }) => new Promise<void>(resolve => {
165+
const closed = page.evaluate(({ url, incomingCount, outgoingText, outgoingBinary, delayMs }) => new Promise<void>(resolve => {
153166
let count = 0;
154167
const ws = new WebSocket(url);
155-
ws.addEventListener('message', () => {
168+
ws.addEventListener('message', async () => {
156169
if (++count < incomingCount)
157170
return;
158-
for (const text of outgoingText)
171+
for (const text of outgoingText) {
159172
ws.send(text);
160-
for (const binary of outgoingBinary)
173+
await new Promise(resolve => setTimeout(resolve, delayMs));
174+
}
175+
for (const binary of outgoingBinary) {
176+
await new Promise(resolve => setTimeout(resolve, delayMs));
161177
ws.send(new Uint8Array(binary));
178+
}
162179
ws.close();
163180
});
164181
ws.addEventListener('close', () => resolve());
165-
}), { url: wsUrl, incomingCount: incomingText.length + incomingBinary.length, outgoingText, outgoingBinary });
182+
}), { url: wsUrl, incomingCount, outgoingText, outgoingBinary, delayMs });
166183
await closed;
167184
const afterMs = Date.now();
168185

@@ -208,6 +225,7 @@ async function testWebSocketMessages(contextFactory, server, testInfo, content,
208225
}
209226
expect(messages[0].time).toBeLessThanOrEqual(messages[1].time);
210227
expect(wsEntry.time).toBeGreaterThanOrEqual(messages[messages.length - 1].time - messages[0].time);
228+
expect(wsEntry.time).toBeGreaterThanOrEqual(delayMs * (incomingCount + outgoingCount));
211229
}
212230

213231
it('should embed websocket messages', async ({ contextFactory, server, channel }, testInfo) => {

0 commit comments

Comments
 (0)