mirror of
https://github.com/microsoft/playwright.git
synced 2025-06-26 21:40:17 +00:00
fix: throw pretty error if opening userDataDir twice (#36007)
This commit is contained in:
parent
9d40340099
commit
bc92cb44fe
@ -21,6 +21,7 @@ import { BrowserReadyState, BrowserType, kNoXServerRunningError } from '../brows
|
||||
import { BidiBrowser } from './bidiBrowser';
|
||||
import { kBrowserCloseMessageId } from './bidiConnection';
|
||||
import { chromiumSwitches } from '../chromium/chromiumSwitches';
|
||||
import { RecentLogsCollector } from '../utils/debugLogger';
|
||||
|
||||
import type { BrowserOptions } from '../browser';
|
||||
import type { SdkObject } from '../instrumentation';
|
||||
@ -35,13 +36,23 @@ export class BidiChromium extends BrowserType {
|
||||
super(parent, 'bidi');
|
||||
}
|
||||
|
||||
override async connectToTransport(transport: ConnectionTransport, options: BrowserOptions): Promise<BidiBrowser> {
|
||||
override async connectToTransport(transport: ConnectionTransport, options: BrowserOptions, browserLogsCollector: RecentLogsCollector): Promise<BidiBrowser> {
|
||||
// Chrome doesn't support Bidi, we create Bidi over CDP which is used by Chrome driver.
|
||||
// bidiOverCdp depends on chromium-bidi which we only have in devDependencies, so
|
||||
// we load bidiOverCdp dynamically.
|
||||
const bidiTransport = await require('./bidiOverCdp').connectBidiOverCdp(transport);
|
||||
(transport as any)[kBidiOverCdpWrapper] = bidiTransport;
|
||||
try {
|
||||
return BidiBrowser.connect(this.attribution.playwright, bidiTransport, options);
|
||||
} catch (e) {
|
||||
if (browserLogsCollector.recentLogs().some(log => log.includes('Failed to create a ProcessSingleton for your profile directory.'))) {
|
||||
throw new Error(
|
||||
'Failed to create a ProcessSingleton for your profile directory. ' +
|
||||
'This usually means that the profile is already in use by another instance of Chromium.'
|
||||
);
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
override doRewriteStartupLog(error: ProtocolError): ProtocolError {
|
||||
@ -155,6 +166,10 @@ export class BidiChromium extends BrowserType {
|
||||
|
||||
class ChromiumReadyState extends BrowserReadyState {
|
||||
override onBrowserOutput(message: string): void {
|
||||
if (message.includes('Failed to create a ProcessSingleton for your profile directory.')) {
|
||||
this._wsEndpoint.reject(new Error('Failed to create a ProcessSingleton for your profile directory. ' +
|
||||
'This usually means that the profile is already in use by another instance of Chromium.'));
|
||||
}
|
||||
const match = message.match(/DevTools listening on (.*)/);
|
||||
if (match)
|
||||
this._wsEndpoint.resolve(match[1]);
|
||||
|
@ -157,7 +157,7 @@ export abstract class BrowserType extends SdkObject {
|
||||
if (persistent)
|
||||
validateBrowserContextOptions(persistent, browserOptions);
|
||||
copyTestHooks(options, browserOptions);
|
||||
const browser = await this.connectToTransport(transport, browserOptions);
|
||||
const browser = await this.connectToTransport(transport, browserOptions, browserLogsCollector);
|
||||
(browser as any)._userDataDirForTest = userDataDir;
|
||||
// We assume no control when using custom arguments, and do not prepare the default context in that case.
|
||||
if (persistent && !options.ignoreAllDefaultArgs)
|
||||
@ -342,7 +342,7 @@ export abstract class BrowserType extends SdkObject {
|
||||
}
|
||||
|
||||
abstract defaultArgs(options: types.LaunchOptions, isPersistent: boolean, userDataDir: string): string[];
|
||||
abstract connectToTransport(transport: ConnectionTransport, options: BrowserOptions): Promise<Browser>;
|
||||
abstract connectToTransport(transport: ConnectionTransport, options: BrowserOptions, browserLogsCollector: RecentLogsCollector): Promise<Browser>;
|
||||
abstract amendEnvironment(env: Env, userDataDir: string, executable: string, browserArguments: string[]): Env;
|
||||
abstract doRewriteStartupLog(error: ProtocolError): ProtocolError;
|
||||
abstract attemptToGracefullyCloseBrowser(transport: ConnectionTransport): void;
|
||||
|
@ -126,13 +126,23 @@ export class Chromium extends BrowserType {
|
||||
return directory ? new CRDevTools(path.join(directory, 'devtools-preferences.json')) : undefined;
|
||||
}
|
||||
|
||||
override async connectToTransport(transport: ConnectionTransport, options: BrowserOptions): Promise<CRBrowser> {
|
||||
override async connectToTransport(transport: ConnectionTransport, options: BrowserOptions, browserLogsCollector: RecentLogsCollector): Promise<CRBrowser> {
|
||||
let devtools = this._devtools;
|
||||
if ((options as any).__testHookForDevTools) {
|
||||
devtools = this._createDevTools();
|
||||
await (options as any).__testHookForDevTools(devtools);
|
||||
}
|
||||
return CRBrowser.connect(this.attribution.playwright, transport, options, devtools);
|
||||
try {
|
||||
return await CRBrowser.connect(this.attribution.playwright, transport, options, devtools);
|
||||
} catch (e) {
|
||||
if (browserLogsCollector.recentLogs().some(log => log.includes('Failed to create a ProcessSingleton for your profile directory.'))) {
|
||||
throw new Error(
|
||||
'Failed to create a ProcessSingleton for your profile directory. ' +
|
||||
'This usually means that the profile is already in use by another instance of Chromium.'
|
||||
);
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
override doRewriteStartupLog(error: ProtocolError): ProtocolError {
|
||||
@ -358,6 +368,10 @@ export class Chromium extends BrowserType {
|
||||
|
||||
class ChromiumReadyState extends BrowserReadyState {
|
||||
override onBrowserOutput(message: string): void {
|
||||
if (message.includes('Failed to create a ProcessSingleton for your profile directory.')) {
|
||||
this._wsEndpoint.reject(new Error('Failed to create a ProcessSingleton for your profile directory. ' +
|
||||
'This usually means that the profile is already in use by another instance of Chromium.'));
|
||||
}
|
||||
const match = message.match(/DevTools listening on (.*)/);
|
||||
if (match)
|
||||
this._wsEndpoint.resolve(match[1]);
|
||||
|
@ -630,3 +630,33 @@ test.describe('PW_EXPERIMENTAL_SERVICE_WORKER_NETWORK_EVENTS=1', () => {
|
||||
expect(req.headers['x-custom-header']).toBe('custom!');
|
||||
});
|
||||
});
|
||||
|
||||
test('should throw when connecting twice to an already running persistent context (--remote-debugging-port)', async ({ browserType, createUserDataDir, platform, isHeadlessShell }) => {
|
||||
test.skip(isHeadlessShell, 'Headless shell does not create a ProcessSingleton');
|
||||
test.fixme(platform === 'win32', 'Windows does not print something to the console when the profile is already in use by another instance of Chromium.');
|
||||
const userDataDir = await createUserDataDir();
|
||||
const browser = await browserType.launchPersistentContext(userDataDir, {
|
||||
cdpPort: 9222,
|
||||
} as any);
|
||||
try {
|
||||
const error = await browserType.launchPersistentContext(userDataDir, {
|
||||
cdpPort: 9223,
|
||||
} as any).catch(e => e);
|
||||
expect(error.message).toContain('This usually means that the profile is already in use by another instance of Chromium.');
|
||||
} finally {
|
||||
await browser.close();
|
||||
}
|
||||
});
|
||||
|
||||
test('should throw when connecting twice to an already running persistent context (--remote-debugging-pipe)', async ({ browserType, createUserDataDir, platform, isHeadlessShell }) => {
|
||||
test.skip(isHeadlessShell, 'Headless shell does not create a ProcessSingleton');
|
||||
test.fixme(platform === 'win32', 'Windows does not print something to the console when the profile is already in use by another instance of Chromium.');
|
||||
const userDataDir = await createUserDataDir();
|
||||
const browser = await browserType.launchPersistentContext(userDataDir);
|
||||
try {
|
||||
const error = await browserType.launchPersistentContext(userDataDir).catch(e => e);
|
||||
expect(error.message).toContain('This usually means that the profile is already in use by another instance of Chromium.');
|
||||
} finally {
|
||||
await browser.close();
|
||||
}
|
||||
});
|
||||
|
Loading…
x
Reference in New Issue
Block a user