feat(firefox): support WebSockets on Firefox (#4289)
This commit is contained in:
parent
333916a83d
commit
7fbbd1822e
|
|
@ -8,7 +8,7 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "firefox",
|
"name": "firefox",
|
||||||
"revision": "1197",
|
"revision": "1198",
|
||||||
"download": true
|
"download": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -84,6 +84,11 @@ export class FFPage implements PageDelegate {
|
||||||
helper.addEventListener(this._session, 'Page.dispatchMessageFromWorker', this._onDispatchMessageFromWorker.bind(this)),
|
helper.addEventListener(this._session, 'Page.dispatchMessageFromWorker', this._onDispatchMessageFromWorker.bind(this)),
|
||||||
helper.addEventListener(this._session, 'Page.crashed', this._onCrashed.bind(this)),
|
helper.addEventListener(this._session, 'Page.crashed', this._onCrashed.bind(this)),
|
||||||
helper.addEventListener(this._session, 'Page.screencastStarted', this._onScreencastStarted.bind(this)),
|
helper.addEventListener(this._session, 'Page.screencastStarted', this._onScreencastStarted.bind(this)),
|
||||||
|
|
||||||
|
helper.addEventListener(this._session, 'Page.webSocketCreated', this._onWebSocketCreated.bind(this)),
|
||||||
|
helper.addEventListener(this._session, 'Page.webSocketClosed', this._onWebSocketClosed.bind(this)),
|
||||||
|
helper.addEventListener(this._session, 'Page.webSocketFrameReceived', this._onWebSocketFrameReceived.bind(this)),
|
||||||
|
helper.addEventListener(this._session, 'Page.webSocketFrameSent', this._onWebSocketFrameSent.bind(this)),
|
||||||
];
|
];
|
||||||
this._pagePromise = new Promise(f => this._pageCallback = f);
|
this._pagePromise = new Promise(f => this._pageCallback = f);
|
||||||
session.once(FFSessionEvents.Disconnected, () => this._page._didDisconnect());
|
session.once(FFSessionEvents.Disconnected, () => this._page._didDisconnect());
|
||||||
|
|
@ -100,6 +105,25 @@ export class FFPage implements PageDelegate {
|
||||||
return this._pagePromise;
|
return this._pagePromise;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_onWebSocketCreated(event: Protocol.Page.webSocketCreatedPayload) {
|
||||||
|
this._page._frameManager.onWebSocketCreated(webSocketId(event.frameId, event.wsid), event.requestURL);
|
||||||
|
this._page._frameManager.onWebSocketRequest(webSocketId(event.frameId, event.wsid));
|
||||||
|
}
|
||||||
|
|
||||||
|
_onWebSocketClosed(event: Protocol.Page.webSocketClosedPayload) {
|
||||||
|
if (event.error)
|
||||||
|
this._page._frameManager.webSocketError(webSocketId(event.frameId, event.wsid), event.error);
|
||||||
|
this._page._frameManager.webSocketClosed(webSocketId(event.frameId, event.wsid));
|
||||||
|
}
|
||||||
|
|
||||||
|
_onWebSocketFrameReceived(event: Protocol.Page.webSocketFrameReceivedPayload) {
|
||||||
|
this._page._frameManager.webSocketFrameReceived(webSocketId(event.frameId, event.wsid), event.opcode, event.data);
|
||||||
|
}
|
||||||
|
|
||||||
|
_onWebSocketFrameSent(event: Protocol.Page.webSocketFrameSentPayload) {
|
||||||
|
this._page._frameManager.onWebSocketFrameSent(webSocketId(event.frameId, event.wsid), event.opcode, event.data);
|
||||||
|
}
|
||||||
|
|
||||||
_onExecutionContextCreated(payload: Protocol.Runtime.executionContextCreatedPayload) {
|
_onExecutionContextCreated(payload: Protocol.Runtime.executionContextCreatedPayload) {
|
||||||
const {executionContextId, auxData} = payload;
|
const {executionContextId, auxData} = payload;
|
||||||
const frame = this._page._frameManager.frame(auxData ? auxData.frameId : null);
|
const frame = this._page._frameManager.frame(auxData ? auxData.frameId : null);
|
||||||
|
|
@ -500,3 +524,7 @@ export class FFPage implements PageDelegate {
|
||||||
return result.handle;
|
return result.handle;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function webSocketId(frameId: string, wsid: string): string {
|
||||||
|
return `${frameId}---${wsid}`;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -413,6 +413,34 @@ export module Protocol {
|
||||||
screencastId: string;
|
screencastId: string;
|
||||||
file: string;
|
file: string;
|
||||||
}
|
}
|
||||||
|
export type webSocketCreatedPayload = {
|
||||||
|
frameId: string;
|
||||||
|
wsid: string;
|
||||||
|
requestURL: string;
|
||||||
|
}
|
||||||
|
export type webSocketOpenedPayload = {
|
||||||
|
frameId: string;
|
||||||
|
requestId: string;
|
||||||
|
wsid: string;
|
||||||
|
effectiveURL: string;
|
||||||
|
}
|
||||||
|
export type webSocketClosedPayload = {
|
||||||
|
frameId: string;
|
||||||
|
wsid: string;
|
||||||
|
error: string;
|
||||||
|
}
|
||||||
|
export type webSocketFrameSentPayload = {
|
||||||
|
frameId: string;
|
||||||
|
wsid: string;
|
||||||
|
opcode: number;
|
||||||
|
data: string;
|
||||||
|
}
|
||||||
|
export type webSocketFrameReceivedPayload = {
|
||||||
|
frameId: string;
|
||||||
|
wsid: string;
|
||||||
|
opcode: number;
|
||||||
|
data: string;
|
||||||
|
}
|
||||||
export type closeParameters = {
|
export type closeParameters = {
|
||||||
runBeforeUnload?: boolean;
|
runBeforeUnload?: boolean;
|
||||||
};
|
};
|
||||||
|
|
@ -979,6 +1007,11 @@ export module Protocol {
|
||||||
"Page.workerDestroyed": Page.workerDestroyedPayload;
|
"Page.workerDestroyed": Page.workerDestroyedPayload;
|
||||||
"Page.dispatchMessageFromWorker": Page.dispatchMessageFromWorkerPayload;
|
"Page.dispatchMessageFromWorker": Page.dispatchMessageFromWorkerPayload;
|
||||||
"Page.screencastStarted": Page.screencastStartedPayload;
|
"Page.screencastStarted": Page.screencastStartedPayload;
|
||||||
|
"Page.webSocketCreated": Page.webSocketCreatedPayload;
|
||||||
|
"Page.webSocketOpened": Page.webSocketOpenedPayload;
|
||||||
|
"Page.webSocketClosed": Page.webSocketClosedPayload;
|
||||||
|
"Page.webSocketFrameSent": Page.webSocketFrameSentPayload;
|
||||||
|
"Page.webSocketFrameReceived": Page.webSocketFrameReceivedPayload;
|
||||||
"Runtime.executionContextCreated": Runtime.executionContextCreatedPayload;
|
"Runtime.executionContextCreated": Runtime.executionContextCreatedPayload;
|
||||||
"Runtime.executionContextDestroyed": Runtime.executionContextDestroyedPayload;
|
"Runtime.executionContextDestroyed": Runtime.executionContextDestroyedPayload;
|
||||||
"Runtime.console": Runtime.consolePayload;
|
"Runtime.console": Runtime.consolePayload;
|
||||||
|
|
|
||||||
|
|
@ -34,16 +34,6 @@ if (browserName !== 'chromium') {
|
||||||
api.delete('cDPSession.detach');
|
api.delete('cDPSession.detach');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (browserName === 'firefox') {
|
|
||||||
// WebSockets on FF are work in progress.
|
|
||||||
api.delete('webSocket.url');
|
|
||||||
api.delete('webSocket.emit("close")');
|
|
||||||
api.delete('webSocket.emit("socketerror")');
|
|
||||||
api.delete('webSocket.emit("framereceived")');
|
|
||||||
api.delete('webSocket.emit("framesent")');
|
|
||||||
api.delete('page.emit("websocket")');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Some permissions tests are disabled in webkit. See permissions.jest.js
|
// Some permissions tests are disabled in webkit. See permissions.jest.js
|
||||||
if (browserName === 'webkit')
|
if (browserName === 'webkit')
|
||||||
api.delete('browserContext.clearPermissions');
|
api.delete('browserContext.clearPermissions');
|
||||||
|
|
@ -77,4 +67,4 @@ function * getCoverageFiles(dir) {
|
||||||
else
|
else
|
||||||
yield path.join(dir, entry.name);
|
yield path.join(dir, entry.name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,6 @@
|
||||||
import { it, describe, expect } from './fixtures';
|
import { it, describe, expect } from './fixtures';
|
||||||
|
|
||||||
describe('web socket', (test, { browserName }) => {
|
describe('web socket', (test, { browserName }) => {
|
||||||
test.fixme(browserName === 'firefox');
|
|
||||||
}, () => {
|
}, () => {
|
||||||
it('should work', async ({ page, server }) => {
|
it('should work', async ({ page, server }) => {
|
||||||
const value = await page.evaluate(port => {
|
const value = await page.evaluate(port => {
|
||||||
|
|
@ -47,7 +46,7 @@ describe('web socket', (test, { browserName }) => {
|
||||||
expect(log.join(':')).toBe(`open<ws://localhost:${server.PORT}/ws>:close`);
|
expect(log.join(':')).toBe(`open<ws://localhost:${server.PORT}/ws>:close`);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should emit frame events', async ({ page, server }) => {
|
it('should emit frame events', async ({ page, server, isFirefox }) => {
|
||||||
let socketClosed;
|
let socketClosed;
|
||||||
const socketClosePromise = new Promise(f => socketClosed = f);
|
const socketClosePromise = new Promise(f => socketClosed = f);
|
||||||
const log = [];
|
const log = [];
|
||||||
|
|
@ -63,7 +62,10 @@ describe('web socket', (test, { browserName }) => {
|
||||||
ws.addEventListener('message', () => { ws.close(); });
|
ws.addEventListener('message', () => { ws.close(); });
|
||||||
}, server.PORT);
|
}, server.PORT);
|
||||||
await socketClosePromise;
|
await socketClosePromise;
|
||||||
expect(log.join(':')).toBe('open:sent<outgoing>:received<incoming>:close');
|
if (isFirefox)
|
||||||
|
expect(log.join(':')).toBe('open:received<incoming>:sent<outgoing>:close');
|
||||||
|
else
|
||||||
|
expect(log.join(':')).toBe('open:sent<outgoing>:received<incoming>:close');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should emit binary frame events', async ({ page, server }) => {
|
it('should emit binary frame events', async ({ page, server }) => {
|
||||||
|
|
@ -91,7 +93,7 @@ describe('web socket', (test, { browserName }) => {
|
||||||
expect(sent[1][i]).toBe(i);
|
expect(sent[1][i]).toBe(i);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should emit error', async ({page, server}) => {
|
it('should emit error', async ({page, server, isFirefox}) => {
|
||||||
let callback;
|
let callback;
|
||||||
const result = new Promise(f => callback = f);
|
const result = new Promise(f => callback = f);
|
||||||
page.on('websocket', ws => ws.on('socketerror', callback));
|
page.on('websocket', ws => ws.on('socketerror', callback));
|
||||||
|
|
@ -99,6 +101,9 @@ describe('web socket', (test, { browserName }) => {
|
||||||
new WebSocket('ws://localhost:' + port + '/bogus-ws');
|
new WebSocket('ws://localhost:' + port + '/bogus-ws');
|
||||||
}, server.PORT);
|
}, server.PORT);
|
||||||
const message = await result;
|
const message = await result;
|
||||||
expect(message).toContain(': 400');
|
if (isFirefox)
|
||||||
|
expect(message).toBe('CLOSE_ABNORMAL');
|
||||||
|
else
|
||||||
|
expect(message).toContain(': 400');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue