From 25a4c7b3dfd64df47c18a829719a7e3d87a18ab1 Mon Sep 17 00:00:00 2001 From: Ross Wollman Date: Sun, 22 Aug 2021 09:04:47 -0700 Subject: [PATCH] feat(launchServer): accept wsPath option (#8353) --- docs/src/api/class-browsertype.md | 12 ++++++++++++ src/browserServerImpl.ts | 6 +++++- src/client/types.ts | 1 + tests/browsertype-launch-server.spec.ts | 20 ++++++++++++++++++++ types/types.d.ts | 8 ++++++++ 5 files changed, 46 insertions(+), 1 deletion(-) diff --git a/docs/src/api/class-browsertype.md b/docs/src/api/class-browsertype.md index 9539dcc812..024a85bec1 100644 --- a/docs/src/api/class-browsertype.md +++ b/docs/src/api/class-browsertype.md @@ -284,6 +284,18 @@ const { chromium } = require('playwright'); // Or 'webkit' or 'firefox'. Port to use for the web socket. Defaults to 0 that picks any available port. +### option: BrowserType.launchServer.wsPath +- `wsPath` <[string]> + +Path at which to serve the Browser Server. For security, this defaults to an +unguessable string. + +:::warning +Any process or web page (including those running in Playwright) with knowledge +of the `wsPath` can take control of the OS user. For this reason, you should +use an unguessable token when using this option. +::: + ## method: BrowserType.name - returns: <[string]> diff --git a/src/browserServerImpl.ts b/src/browserServerImpl.ts index 92c28a4ac8..77c427e282 100644 --- a/src/browserServerImpl.ts +++ b/src/browserServerImpl.ts @@ -52,9 +52,13 @@ export class BrowserServerLauncherImpl implements BrowserServerLauncher { env: options.env ? envObjectToArray(options.env) : undefined, }, toProtocolLogger(options.logger)); + let path = `/${createGuid()}`; + if (options.wsPath) + path = options.wsPath.startsWith('/') ? options.wsPath : `/${options.wsPath}`; + // 2. Start the server const delegate: PlaywrightServerDelegate = { - path: '/' + createGuid(), + path, allowMultipleClients: true, onClose: () => {}, onConnect: this._onConnect.bind(this, playwright, browser), diff --git a/src/client/types.ts b/src/client/types.ts index fe7fde4c86..ee50ac3f22 100644 --- a/src/client/types.ts +++ b/src/client/types.ts @@ -100,6 +100,7 @@ export type LaunchServerOptions = { downloadsPath?: string, chromiumSandbox?: boolean, port?: number, + wsPath?: string, logger?: Logger, } & FirefoxUserPrefs; diff --git a/tests/browsertype-launch-server.spec.ts b/tests/browsertype-launch-server.spec.ts index 917216317b..c23c05006a 100644 --- a/tests/browsertype-launch-server.spec.ts +++ b/tests/browsertype-launch-server.spec.ts @@ -33,6 +33,26 @@ it.describe('launch server', () => { await browserServer.close(); }); + it('should work with wsPath', async ({browserType, browserOptions}) => { + const wsPath = '/unguessable-token'; + const browserServer = await browserType.launchServer({ ...browserOptions, wsPath }); + expect(browserServer.wsEndpoint()).toMatch(/:\d+\/unguessable-token$/); + await browserServer.close(); + }); + + it('should work when wsPath is missing leading slash', async ({browserType, browserOptions}) => { + const wsPath = 'unguessable-token'; + const browserServer = await browserType.launchServer({ ...browserOptions, wsPath }); + expect(browserServer.wsEndpoint()).toMatch(/:\d+\/unguessable-token$/); + await browserServer.close(); + }); + + it('should default to random wsPath', async ({browserType, browserOptions}) => { + const browserServer = await browserType.launchServer({ ...browserOptions }); + expect(browserServer.wsEndpoint()).toMatch(/:\d+\/[a-f\d]{32}$/); + await browserServer.close(); + }); + it('should provide an error when ws endpoint is incorrect', async ({browserType, browserOptions}) => { const browserServer = await browserType.launchServer(browserOptions); const error = await browserType.connect({ wsEndpoint: browserServer.wsEndpoint() + '-foo' }).catch(e => e); diff --git a/types/types.d.ts b/types/types.d.ts index 17ed68156e..33c6ef99bc 100644 --- a/types/types.d.ts +++ b/types/types.d.ts @@ -8725,6 +8725,14 @@ export interface BrowserType { * If specified, traces are saved into this directory. */ tracesDir?: string; + + /** + * Path at which to serve the Browser Server. For security, this defaults to an unguessable string. + * + * > NOTE: Any process or web page (including those running in Playwright) with knowledge of the `wsPath` can take control + * of the OS user. For this reason, you should use an unguessable token when using this option. + */ + wsPath?: string; }): Promise; /**