Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 12 additions & 5 deletions docs/src/api/class-browsertype.md
Original file line number Diff line number Diff line change
Expand Up @@ -211,12 +211,12 @@ A CDP websocket endpoint or http url to connect to. For example `http://localhos

Additional HTTP headers to be sent with connect request. Optional.

### option: BrowserType.connectOverCDP.slowMo
* since: v1.11
- `slowMo` <[float]>
### option: BrowserType.connectOverCDP.isLocal
* since: v1.58
- `isLocal` <[boolean]>

Slows down Playwright operations by the specified amount of milliseconds. Useful so that you
can see what is going on. Defaults to 0.
Tells Playwright that it runs on the same host as the CDP server. It will enable certain optimizations that rely upon
the file system being the same between Playwright and the Browser.

### option: BrowserType.connectOverCDP.logger
* since: v1.14
Expand All @@ -226,6 +226,13 @@ can see what is going on. Defaults to 0.

Logger sink for Playwright logging. Optional.

### option: BrowserType.connectOverCDP.slowMo
* since: v1.11
- `slowMo` <[float]>

Slows down Playwright operations by the specified amount of milliseconds. Useful so that you
can see what is going on. Defaults to 0.

### option: BrowserType.connectOverCDP.timeout
* since: v1.11
- `timeout` <[float]>
Expand Down
6 changes: 6 additions & 0 deletions packages/playwright-client/types/types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22046,6 +22046,12 @@ export interface ConnectOverCDPOptions {
*/
headers?: { [key: string]: string; };

/**
* Tells Playwright that it runs on the same host as the CDP server. It will enable certain optimizations that rely
* upon the file system being the same between Playwright and the Browser.
*/
isLocal?: boolean;

/**
* Logger sink for Playwright logging. Optional.
* @deprecated The logs received by the logger are incomplete. Please use tracing instead.
Expand Down
1 change: 1 addition & 0 deletions packages/playwright-core/src/client/browserType.ts
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,7 @@ export class BrowserType extends ChannelOwner<channels.BrowserTypeChannel> imple
headers,
slowMo: params.slowMo,
timeout: new TimeoutSettings(this._platform).timeout(params),
isLocal: params.isLocal,
});
const browser = Browser.from(result.browser);
browser._connectToBrowserType(this, {}, params.logger);
Expand Down
1 change: 1 addition & 0 deletions packages/playwright-core/src/protocol/validator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -623,6 +623,7 @@ scheme.BrowserTypeConnectOverCDPParams = tObject({
headers: tOptional(tArray(tType('NameValue'))),
slowMo: tOptional(tFloat),
timeout: tFloat,
isLocal: tOptional(tBoolean),
});
scheme.BrowserTypeConnectOverCDPResult = tObject({
browser: tChannel(['Browser']),
Expand Down
2 changes: 1 addition & 1 deletion packages/playwright-core/src/server/browserType.ts
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,7 @@ export abstract class BrowserType extends SdkObject {
await fs.promises.mkdir(options.tracesDir, { recursive: true });
}

async connectOverCDP(progress: Progress, endpointURL: string, options: { slowMo?: number, timeout?: number, headers?: types.HeadersArray }): Promise<Browser> {
async connectOverCDP(progress: Progress, endpointURL: string, options: { slowMo?: number, timeout?: number, headers?: types.HeadersArray, isLocal?: boolean }): Promise<Browser> {
throw new Error('CDP connections are only supported by Chromium');
}

Expand Down
7 changes: 4 additions & 3 deletions packages/playwright-core/src/server/chromium/chromium.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,11 +76,11 @@ export class Chromium extends BrowserType {
return super.launchPersistentContext(progress, userDataDir, options);
}

override async connectOverCDP(progress: Progress, endpointURL: string, options: { slowMo?: number, headers?: types.HeadersArray }) {
override async connectOverCDP(progress: Progress, endpointURL: string, options: { slowMo?: number, headers?: types.HeadersArray, isLocal?: boolean }) {
return await this._connectOverCDPInternal(progress, endpointURL, options);
}

async _connectOverCDPInternal(progress: Progress, endpointURL: string, options: types.LaunchOptions & { headers?: types.HeadersArray }, onClose?: () => Promise<void>) {
async _connectOverCDPInternal(progress: Progress, endpointURL: string, options: types.LaunchOptions & { headers?: types.HeadersArray, isLocal?: boolean }, onClose?: () => Promise<void>) {
let headersMap: { [key: string]: string; } | undefined;
if (options.headers)
headersMap = headersArrayToObject(options.headers, false);
Expand Down Expand Up @@ -125,7 +125,8 @@ export class Chromium extends BrowserType {
};
validateBrowserContextOptions(persistent, browserOptions);
const browser = await progress.race(CRBrowser.connect(this.attribution.playwright, chromeTransport, browserOptions));
browser._isCollocatedWithServer = false;
if (!options.isLocal)
browser._isCollocatedWithServer = false;
browser.on(Browser.Events.Disconnected, doCleanup);
return browser;
} catch (error) {
Expand Down
6 changes: 6 additions & 0 deletions packages/playwright-core/types/types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22046,6 +22046,12 @@ export interface ConnectOverCDPOptions {
*/
headers?: { [key: string]: string; };

/**
* Tells Playwright that it runs on the same host as the CDP server. It will enable certain optimizations that rely
* upon the file system being the same between Playwright and the Browser.
*/
isLocal?: boolean;

/**
* Logger sink for Playwright logging. Optional.
* @deprecated The logs received by the logger are incomplete. Please use tracing instead.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ export class ExtensionContextFactory implements BrowserContextFactory {
private async _obtainBrowser(clientInfo: ClientInfo, abortSignal: AbortSignal, toolName: string | undefined): Promise<playwright.Browser> {
const relay = await this._startRelay(abortSignal);
await relay.ensureExtensionConnectionForMCPContext(clientInfo, abortSignal, toolName);
return await playwright.chromium.connectOverCDP(relay.cdpEndpoint());
return await playwright.chromium.connectOverCDP(relay.cdpEndpoint(), { isLocal: true });
}

private async _startRelay(abortSignal: AbortSignal) {
Expand Down
26 changes: 0 additions & 26 deletions packages/playwright/src/mcp/program.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,10 @@ import * as mcpServer from './sdk/server';
import { commaSeparatedList, dotenvFileLoader, enumParser, headerParser, numberParser, resolutionParser, resolveCLIConfig, semicolonSeparatedList } from './browser/config';
import { setupExitWatchdog } from './browser/watchdog';
import { contextFactory } from './browser/browserContextFactory';
import { ProxyBackend } from './sdk/proxyBackend';
import { BrowserServerBackend } from './browser/browserServerBackend';
import { ExtensionContextFactory } from './extension/extensionContextFactory';

import type { Command } from 'playwright-core/lib/utilsBundle';
import type { MCPProvider } from './sdk/proxyBackend';

export function decorateCommand(command: Command, version: string) {
command
Expand Down Expand Up @@ -73,7 +71,6 @@ export function decorateCommand(command: Command, version: string) {
.option('--user-agent <ua string>', 'specify user agent string')
.option('--user-data-dir <path>', 'path to the user data directory. If not specified, a temporary directory will be created.')
.option('--viewport-size <size>', 'specify browser viewport size in pixels, for example "1280x720"', resolutionParser.bind(null, '--viewport-size'))
.addOption(new ProgramOption('--connect-tool', 'Allow to switch between different browser connection methods.').hideHelp())
.addOption(new ProgramOption('--vision', 'Legacy option, use --caps=vision instead').hideHelp())
.action(async options => {
setupExitWatchdog();
Expand Down Expand Up @@ -108,29 +105,6 @@ export function decorateCommand(command: Command, version: string) {
return;
}

if (options.connectTool) {
const providers: MCPProvider[] = [
{
name: 'default',
description: 'Starts standalone browser',
connect: () => mcpServer.wrapInProcess(new BrowserServerBackend(config, browserContextFactory)),
},
{
name: 'extension',
description: 'Connect to a browser using the Playwright MCP extension',
connect: () => mcpServer.wrapInProcess(new BrowserServerBackend(config, extensionContextFactory)),
},
];
const factory: mcpServer.ServerBackendFactory = {
name: 'Playwright w/ switch',
nameInConfig: 'playwright-switch',
version,
create: () => new ProxyBackend(providers),
};
await mcpServer.start(factory, config.server);
return;
}

const factory: mcpServer.ServerBackendFactory = {
name: 'Playwright',
nameInConfig: 'playwright',
Expand Down
1 change: 0 additions & 1 deletion packages/playwright/src/mcp/sdk/exports.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
*/

export * from './inProcessTransport';
export * from './proxyBackend';
export * from './server';
export * from './tool';
export * from './http';
134 changes: 0 additions & 134 deletions packages/playwright/src/mcp/sdk/proxyBackend.ts

This file was deleted.

2 changes: 2 additions & 0 deletions packages/protocol/src/channels.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1119,10 +1119,12 @@ export type BrowserTypeConnectOverCDPParams = {
headers?: NameValue[],
slowMo?: number,
timeout: number,
isLocal?: boolean,
};
export type BrowserTypeConnectOverCDPOptions = {
headers?: NameValue[],
slowMo?: number,
isLocal?: boolean,
};
export type BrowserTypeConnectOverCDPResult = {
browser: BrowserChannel,
Expand Down
1 change: 1 addition & 0 deletions packages/protocol/src/protocol.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1007,6 +1007,7 @@ BrowserType:
items: NameValue
slowMo: float?
timeout: float
isLocal: boolean?
returns:
browser: Browser
defaultContext: BrowserContext?
Expand Down
16 changes: 16 additions & 0 deletions tests/library/chromium/connect-over-cdp.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -553,6 +553,22 @@ test('setInputFiles should preserve lastModified timestamp', async ({ browserTyp
}
});

test('setInputFiles should use local path when isLocal is set', async ({ browserType, toImpl }) => {
const port = 9339 + test.info().workerIndex;
const browserServer = await browserType.launch({
args: ['--remote-debugging-port=' + port]
});
try {
const cdpBrowser1 = await browserType.connectOverCDP(`http://127.0.0.1:${port}/`);
expect(toImpl(cdpBrowser1)._isCollocatedWithServer).toBe(false);

const cdpBrowser2 = await browserType.connectOverCDP(`http://127.0.0.1:${port}/`, { isLocal: true });
expect(toImpl(cdpBrowser2)._isCollocatedWithServer).toBe(true);
} finally {
await browserServer.close();
}
});

test('should print custom ws close error', async ({ browserType, server }) => {
server.onceWebSocketConnection((ws, request) => {
ws.on('message', message => {
Expand Down
32 changes: 0 additions & 32 deletions tests/mcp/capabilities.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,38 +44,6 @@ test('test snapshot tool list', async ({ client }) => {
]));
});

test('test tool list proxy mode', async ({ startClient }) => {
const { client } = await startClient({
args: ['--connect-tool'],
});
const { tools } = await client.listTools();
expect(new Set(tools.map(t => t.name))).toEqual(new Set([
'browser_click',
'browser_connect', // the extra tool
'browser_console_messages',
'browser_drag',
'browser_evaluate',
'browser_file_upload',
'browser_fill_form',
'browser_handle_dialog',
'browser_hover',
'browser_select_option',
'browser_type',
'browser_close',
'browser_install',
'browser_navigate_back',
'browser_navigate',
'browser_network_requests',
'browser_press_key',
'browser_resize',
'browser_run_code',
'browser_snapshot',
'browser_tabs',
'browser_take_screenshot',
'browser_wait_for',
]));
});

test('test capabilities (pdf)', async ({ startClient }) => {
const { client } = await startClient({
args: ['--caps=pdf'],
Expand Down
Loading