feedback
This commit is contained in:
parent
30506afeba
commit
eeef44455f
|
|
@ -84,7 +84,7 @@ export abstract class Browser extends SdkObject {
|
||||||
|
|
||||||
async newContext(metadata: CallMetadata, options: channels.BrowserNewContextParams): Promise<BrowserContext> {
|
async newContext(metadata: CallMetadata, options: channels.BrowserNewContextParams): Promise<BrowserContext> {
|
||||||
validateBrowserContextOptions(options, this.options);
|
validateBrowserContextOptions(options, this.options);
|
||||||
const clientCertificatesProxy = await createClientCertificatesProxyIfNeeded(options);
|
const clientCertificatesProxy = await createClientCertificatesProxyIfNeeded(options, this.options);
|
||||||
const context = await this.doCreateNewContext(options);
|
const context = await this.doCreateNewContext(options);
|
||||||
context._clientCertificatesProxy = clientCertificatesProxy;
|
context._clientCertificatesProxy = clientCertificatesProxy;
|
||||||
if (options.storageState)
|
if (options.storageState)
|
||||||
|
|
|
||||||
|
|
@ -654,10 +654,10 @@ export function assertBrowserContextIsNotOwned(context: BrowserContext) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function createClientCertificatesProxyIfNeeded(options: channels.BrowserNewContextOptions) {
|
export async function createClientCertificatesProxyIfNeeded(options: channels.BrowserNewContextOptions, browserOptions?: BrowserOptions) {
|
||||||
if (!options.clientCertificates?.length)
|
if (!options.clientCertificates?.length)
|
||||||
return;
|
return;
|
||||||
if (options.proxy?.server)
|
if (options.proxy?.server || browserOptions?.proxy?.server)
|
||||||
throw new Error('Cannot specify both proxy and clientCertificates');
|
throw new Error('Cannot specify both proxy and clientCertificates');
|
||||||
const clientCertificatesProxy = new ClientCertificatesProxy(options);
|
const clientCertificatesProxy = new ClientCertificatesProxy(options);
|
||||||
options.proxy = { server: await clientCertificatesProxy.listen() };
|
options.proxy = { server: await clientCertificatesProxy.listen() };
|
||||||
|
|
@ -699,12 +699,8 @@ export function validateBrowserContextOptions(options: channels.BrowserNewContex
|
||||||
if (options.proxy) {
|
if (options.proxy) {
|
||||||
if (!browserOptions.proxy && browserOptions.isChromium && os.platform() === 'win32')
|
if (!browserOptions.proxy && browserOptions.isChromium && os.platform() === 'win32')
|
||||||
throw new Error(`Browser needs to be launched with the global proxy. If all contexts override the proxy, global proxy will be never used and can be any string, for example "launch({ proxy: { server: 'http://per-context' } })"`);
|
throw new Error(`Browser needs to be launched with the global proxy. If all contexts override the proxy, global proxy will be never used and can be any string, for example "launch({ proxy: { server: 'http://per-context' } })"`);
|
||||||
if (!browserOptions.persistent && options.clientCertificates)
|
|
||||||
throw new Error('Cannot specify both proxy and clientCertificates');
|
|
||||||
options.proxy = normalizeProxySettings(options.proxy);
|
options.proxy = normalizeProxySettings(options.proxy);
|
||||||
}
|
}
|
||||||
if (!browserOptions.persistent && browserOptions.proxy?.server && options.clientCertificates)
|
|
||||||
throw new Error('Cannot specify both proxy and clientCertificates');
|
|
||||||
verifyGeolocation(options.geolocation);
|
verifyGeolocation(options.geolocation);
|
||||||
verifyClientCertificates(options.clientCertificates);
|
verifyClientCertificates(options.clientCertificates);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,7 @@ import type { CallMetadata } from './instrumentation';
|
||||||
import { SdkObject } from './instrumentation';
|
import { SdkObject } from './instrumentation';
|
||||||
import { ManualPromise } from '../utils/manualPromise';
|
import { ManualPromise } from '../utils/manualPromise';
|
||||||
import { type ProtocolError, isProtocolError } from './protocolError';
|
import { type ProtocolError, isProtocolError } from './protocolError';
|
||||||
|
import type { ClientCertificatesProxy } from './socksClientCertificatesInterceptor';
|
||||||
|
|
||||||
export const kNoXServerRunningError = 'Looks like you launched a headed browser without having a XServer running.\n' +
|
export const kNoXServerRunningError = 'Looks like you launched a headed browser without having a XServer running.\n' +
|
||||||
'Set either \'headless: true\' or use \'xvfb-run <your-playwright-app>\' before running Playwright.\n\n<3 Playwright Team';
|
'Set either \'headless: true\' or use \'xvfb-run <your-playwright-app>\' before running Playwright.\n\n<3 Playwright Team';
|
||||||
|
|
@ -77,7 +78,7 @@ export abstract class BrowserType extends SdkObject {
|
||||||
async launchPersistentContext(metadata: CallMetadata, userDataDir: string, options: channels.BrowserTypeLaunchPersistentContextOptions & { useWebSocket?: boolean }): Promise<BrowserContext> {
|
async launchPersistentContext(metadata: CallMetadata, userDataDir: string, options: channels.BrowserTypeLaunchPersistentContextOptions & { useWebSocket?: boolean }): Promise<BrowserContext> {
|
||||||
options = this._validateLaunchOptions(options);
|
options = this._validateLaunchOptions(options);
|
||||||
const controller = new ProgressController(metadata, this);
|
const controller = new ProgressController(metadata, this);
|
||||||
const persistent: channels.BrowserNewContextParams = options;
|
const persistent: channels.BrowserNewContextParams = { ...options };
|
||||||
controller.setLogName('browser');
|
controller.setLogName('browser');
|
||||||
const browser = await controller.run(progress => {
|
const browser = await controller.run(progress => {
|
||||||
return this._innerLaunchWithRetries(progress, options, persistent, helper.debugProtocolLogger(), userDataDir).catch(e => { throw this._rewriteStartupLog(e); });
|
return this._innerLaunchWithRetries(progress, options, persistent, helper.debugProtocolLogger(), userDataDir).catch(e => { throw this._rewriteStartupLog(e); });
|
||||||
|
|
@ -101,9 +102,22 @@ export abstract class BrowserType extends SdkObject {
|
||||||
|
|
||||||
async _innerLaunch(progress: Progress, options: types.LaunchOptions, persistent: channels.BrowserNewContextParams | undefined, protocolLogger: types.ProtocolLogger, maybeUserDataDir?: string): Promise<Browser> {
|
async _innerLaunch(progress: Progress, options: types.LaunchOptions, persistent: channels.BrowserNewContextParams | undefined, protocolLogger: types.ProtocolLogger, maybeUserDataDir?: string): Promise<Browser> {
|
||||||
options.proxy = options.proxy ? normalizeProxySettings(options.proxy) : undefined;
|
options.proxy = options.proxy ? normalizeProxySettings(options.proxy) : undefined;
|
||||||
const clientCertificatesProxy = await createClientCertificatesProxyIfNeeded(persistent ?? {});
|
let clientCertificatesProxy: ClientCertificatesProxy | undefined;
|
||||||
|
if (persistent) {
|
||||||
|
// Note: Any initial requests done by browser will not be intercepted by the client certificates proxy.
|
||||||
|
// We rely when the Page/Frames to ignoreHTTPSErrors to bypass the certificate errors.
|
||||||
|
clientCertificatesProxy = await createClientCertificatesProxyIfNeeded(persistent);
|
||||||
|
options.proxy = persistent.proxy;
|
||||||
|
}
|
||||||
const browserLogsCollector = new RecentLogsCollector();
|
const browserLogsCollector = new RecentLogsCollector();
|
||||||
const { browserProcess, userDataDir, artifactsDir, transport } = await this._launchProcess(progress, options, !!persistent, browserLogsCollector, maybeUserDataDir);
|
let launchInfo;
|
||||||
|
try {
|
||||||
|
launchInfo = await this._launchProcess(progress, options, !!persistent, browserLogsCollector, maybeUserDataDir);
|
||||||
|
} catch (error) {
|
||||||
|
await clientCertificatesProxy?.close();
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
const { browserProcess, userDataDir, artifactsDir, transport } = launchInfo;
|
||||||
if ((options as any).__testHookBeforeCreateBrowser)
|
if ((options as any).__testHookBeforeCreateBrowser)
|
||||||
await (options as any).__testHookBeforeCreateBrowser();
|
await (options as any).__testHookBeforeCreateBrowser();
|
||||||
const browserOptions: BrowserOptions = {
|
const browserOptions: BrowserOptions = {
|
||||||
|
|
@ -127,13 +141,19 @@ export abstract class BrowserType extends SdkObject {
|
||||||
if (persistent)
|
if (persistent)
|
||||||
validateBrowserContextOptions(persistent, browserOptions);
|
validateBrowserContextOptions(persistent, browserOptions);
|
||||||
copyTestHooks(options, browserOptions);
|
copyTestHooks(options, browserOptions);
|
||||||
const browser = await this._connectToTransport(transport, browserOptions);
|
let browser;
|
||||||
|
try {
|
||||||
|
browser = await this._connectToTransport(transport, browserOptions);
|
||||||
|
} catch (error) {
|
||||||
|
await clientCertificatesProxy?.close();
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
(browser as any)._userDataDirForTest = userDataDir;
|
(browser as any)._userDataDirForTest = userDataDir;
|
||||||
|
if (persistent)
|
||||||
|
browser._defaultContext!._clientCertificatesProxy = clientCertificatesProxy;
|
||||||
// We assume no control when using custom arguments, and do not prepare the default context in that case.
|
// We assume no control when using custom arguments, and do not prepare the default context in that case.
|
||||||
if (persistent && !options.ignoreAllDefaultArgs)
|
if (persistent && !options.ignoreAllDefaultArgs)
|
||||||
await browser._defaultContext!._loadDefaultContext(progress);
|
await browser._defaultContext!._loadDefaultContext(progress);
|
||||||
if (persistent)
|
|
||||||
browser._defaultContext!._clientCertificatesProxy = clientCertificatesProxy;
|
|
||||||
return browser;
|
return browser;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
48
packages/playwright-core/types/types.d.ts
vendored
48
packages/playwright-core/types/types.d.ts
vendored
|
|
@ -13222,15 +13222,15 @@ export interface BrowserType<Unused = {}> {
|
||||||
chromiumSandbox?: boolean;
|
chromiumSandbox?: boolean;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An array of client certificates to be used. Each certificate object must have `cert` and `key` or `pfx` to load the
|
* An array of client certificates to be used. Each certificate object must have both `certPath` and `keyPath` or a
|
||||||
* client certificate. Optionally, `passphrase` property should be provided if the private key is encrypted. If the
|
* single `pfxPath` to load the client certificate. Optionally, `passphrase` property should be provided if the
|
||||||
* certificate is valid only for specific URLs, the `url` property should be provided with a glob pattern to match the
|
* private key is encrypted. If the certificate is valid only for specific URLs, the `url` property should be provided
|
||||||
* URLs that the certificate is valid for.
|
* with a glob pattern to match the URLs that the certificate is valid for.
|
||||||
*
|
*
|
||||||
* **NOTE** Using Client Certificates in combination with Proxy Servers is not supported.
|
* **NOTE** Using Client Certificates in combination with Proxy Servers is not supported.
|
||||||
*
|
*
|
||||||
* **NOTE** When using WebKit on macOS, accessing `localhost` might not work as expected. Instead, use
|
* **NOTE** When using WebKit on macOS, accessing `localhost` will not pick up client certificates. You can make it
|
||||||
* `playwright.local` as the hostname.
|
* work by replacing `localhost` with `local.playwright`. Instead, use `playwright.local` as the hostname.
|
||||||
*/
|
*/
|
||||||
clientCertificates?: Array<{
|
clientCertificates?: Array<{
|
||||||
/**
|
/**
|
||||||
|
|
@ -15634,15 +15634,15 @@ export interface APIRequest {
|
||||||
baseURL?: string;
|
baseURL?: string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An array of client certificates to be used. Each certificate object must have `cert` and `key` or `pfx` to load the
|
* An array of client certificates to be used. Each certificate object must have both `certPath` and `keyPath` or a
|
||||||
* client certificate. Optionally, `passphrase` property should be provided if the private key is encrypted. If the
|
* single `pfxPath` to load the client certificate. Optionally, `passphrase` property should be provided if the
|
||||||
* certificate is valid only for specific URLs, the `url` property should be provided with a glob pattern to match the
|
* private key is encrypted. If the certificate is valid only for specific URLs, the `url` property should be provided
|
||||||
* URLs that the certificate is valid for.
|
* with a glob pattern to match the URLs that the certificate is valid for.
|
||||||
*
|
*
|
||||||
* **NOTE** Using Client Certificates in combination with Proxy Servers is not supported.
|
* **NOTE** Using Client Certificates in combination with Proxy Servers is not supported.
|
||||||
*
|
*
|
||||||
* **NOTE** When using WebKit on macOS, accessing `localhost` might not work as expected. Instead, use
|
* **NOTE** When using WebKit on macOS, accessing `localhost` will not pick up client certificates. You can make it
|
||||||
* `playwright.local` as the hostname.
|
* work by replacing `localhost` with `local.playwright`. Instead, use `playwright.local` as the hostname.
|
||||||
*/
|
*/
|
||||||
clientCertificates?: Array<{
|
clientCertificates?: Array<{
|
||||||
/**
|
/**
|
||||||
|
|
@ -16828,15 +16828,15 @@ export interface Browser extends EventEmitter {
|
||||||
bypassCSP?: boolean;
|
bypassCSP?: boolean;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An array of client certificates to be used. Each certificate object must have `cert` and `key` or `pfx` to load the
|
* An array of client certificates to be used. Each certificate object must have both `certPath` and `keyPath` or a
|
||||||
* client certificate. Optionally, `passphrase` property should be provided if the private key is encrypted. If the
|
* single `pfxPath` to load the client certificate. Optionally, `passphrase` property should be provided if the
|
||||||
* certificate is valid only for specific URLs, the `url` property should be provided with a glob pattern to match the
|
* private key is encrypted. If the certificate is valid only for specific URLs, the `url` property should be provided
|
||||||
* URLs that the certificate is valid for.
|
* with a glob pattern to match the URLs that the certificate is valid for.
|
||||||
*
|
*
|
||||||
* **NOTE** Using Client Certificates in combination with Proxy Servers is not supported.
|
* **NOTE** Using Client Certificates in combination with Proxy Servers is not supported.
|
||||||
*
|
*
|
||||||
* **NOTE** When using WebKit on macOS, accessing `localhost` might not work as expected. Instead, use
|
* **NOTE** When using WebKit on macOS, accessing `localhost` will not pick up client certificates. You can make it
|
||||||
* `playwright.local` as the hostname.
|
* work by replacing `localhost` with `local.playwright`. Instead, use `playwright.local` as the hostname.
|
||||||
*/
|
*/
|
||||||
clientCertificates?: Array<{
|
clientCertificates?: Array<{
|
||||||
/**
|
/**
|
||||||
|
|
@ -20303,15 +20303,15 @@ export interface BrowserContextOptions {
|
||||||
bypassCSP?: boolean;
|
bypassCSP?: boolean;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An array of client certificates to be used. Each certificate object must have `cert` and `key` or `pfx` to load the
|
* An array of client certificates to be used. Each certificate object must have both `certPath` and `keyPath` or a
|
||||||
* client certificate. Optionally, `passphrase` property should be provided if the private key is encrypted. If the
|
* single `pfxPath` to load the client certificate. Optionally, `passphrase` property should be provided if the
|
||||||
* certificate is valid only for specific URLs, the `url` property should be provided with a glob pattern to match the
|
* private key is encrypted. If the certificate is valid only for specific URLs, the `url` property should be provided
|
||||||
* URLs that the certificate is valid for.
|
* with a glob pattern to match the URLs that the certificate is valid for.
|
||||||
*
|
*
|
||||||
* **NOTE** Using Client Certificates in combination with Proxy Servers is not supported.
|
* **NOTE** Using Client Certificates in combination with Proxy Servers is not supported.
|
||||||
*
|
*
|
||||||
* **NOTE** When using WebKit on macOS, accessing `localhost` might not work as expected. Instead, use
|
* **NOTE** When using WebKit on macOS, accessing `localhost` will not pick up client certificates. You can make it
|
||||||
* `playwright.local` as the hostname.
|
* work by replacing `localhost` with `local.playwright`. Instead, use `playwright.local` as the hostname.
|
||||||
*/
|
*/
|
||||||
clientCertificates?: Array<{
|
clientCertificates?: Array<{
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
12
packages/playwright/types/test.d.ts
vendored
12
packages/playwright/types/test.d.ts
vendored
|
|
@ -5202,15 +5202,15 @@ export interface PlaywrightTestOptions {
|
||||||
*/
|
*/
|
||||||
colorScheme: ColorScheme;
|
colorScheme: ColorScheme;
|
||||||
/**
|
/**
|
||||||
* An array of client certificates to be used. Each certificate object must have `cert` and `key` or `pfx` to load the
|
* An array of client certificates to be used. Each certificate object must have both `certPath` and `keyPath` or a
|
||||||
* client certificate. Optionally, `passphrase` property should be provided if the private key is encrypted. If the
|
* single `pfxPath` to load the client certificate. Optionally, `passphrase` property should be provided if the
|
||||||
* certificate is valid only for specific URLs, the `url` property should be provided with a glob pattern to match the
|
* private key is encrypted. If the certificate is valid only for specific URLs, the `url` property should be provided
|
||||||
* URLs that the certificate is valid for.
|
* with a glob pattern to match the URLs that the certificate is valid for.
|
||||||
*
|
*
|
||||||
* **NOTE** Using Client Certificates in combination with Proxy Servers is not supported.
|
* **NOTE** Using Client Certificates in combination with Proxy Servers is not supported.
|
||||||
*
|
*
|
||||||
* **NOTE** When using WebKit on macOS, accessing `localhost` might not work as expected. Instead, use
|
* **NOTE** When using WebKit on macOS, accessing `localhost` will not pick up client certificates. You can make it
|
||||||
* `playwright.local` as the hostname.
|
* work by replacing `localhost` with `local.playwright`. Instead, use `playwright.local` as the hostname.
|
||||||
*
|
*
|
||||||
* **Usage**
|
* **Usage**
|
||||||
*
|
*
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue