Skip to content
Closed
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
8 changes: 8 additions & 0 deletions docs/src/api/class-browsertype.md
Original file line number Diff line number Diff line change
Expand Up @@ -322,6 +322,14 @@ describes some differences for Linux users.
### option: BrowserType.launch.ignoreAllDefaultArgs = %%-csharp-java-browser-option-ignorealldefaultargs-%%
* since: v1.9

### option: BrowserType.launch.createPagesInBackground
* since: v1.62
- `createPagesInBackground` <[boolean]>

When set to `true`, new pages are created in the background, so that the headed browser window does not activate and
steal the OS focus from the user. Pages still behave as focused ones. Use [`method: Page.bringToFront`] to activate
the browser window when needed. Currently only implemented for headed Chromium. Defaults to `false`.

## async method: BrowserType.launchPersistentContext
* since: v1.8
- returns: <[BrowserContext]>
Expand Down
8 changes: 8 additions & 0 deletions packages/playwright-client/types/types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23283,6 +23283,14 @@ export interface LaunchOptions {
*/
chromiumSandbox?: boolean;

/**
* When set to `true`, new pages are created in the background, so that the headed browser window does not activate
* and steal the OS focus from the user. Pages still behave as focused ones. Use
* [page.bringToFront()](https://playwright.dev/docs/api/class-page#page-bring-to-front) to activate the browser
* window when needed. Currently only implemented for headed Chromium. Defaults to `false`.
*/
createPagesInBackground?: boolean;

/**
* If specified, accepted downloads are downloaded into this directory. Otherwise, temporary directory is created and
* is deleted when browser is closed. In either case, the downloads are deleted when the browser context they were
Expand Down
2 changes: 2 additions & 0 deletions packages/playwright-core/src/protocol/validator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -982,6 +982,7 @@ scheme.BrowserTypeLaunchParams = tObject({
tracesDir: tOptional(tString),
artifactsDir: tOptional(tString),
chromiumSandbox: tOptional(tBoolean),
createPagesInBackground: tOptional(tBoolean),
firefoxUserPrefs: tOptional(tAny),
cdpPort: tOptional(tInt),
slowMo: tOptional(tFloat),
Expand Down Expand Up @@ -1011,6 +1012,7 @@ scheme.BrowserTypeLaunchPersistentContextParams = tObject({
tracesDir: tOptional(tString),
artifactsDir: tOptional(tString),
chromiumSandbox: tOptional(tBoolean),
createPagesInBackground: tOptional(tBoolean),
firefoxUserPrefs: tOptional(tAny),
cdpPort: tOptional(tInt),
noDefaultViewport: tOptional(tBoolean),
Expand Down
4 changes: 3 additions & 1 deletion packages/playwright-core/src/server/chromium/crBrowser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -370,7 +370,9 @@ export class CRBrowserContext extends BrowserContext<CREventsMap> {
}

override async doCreateNewPage(): Promise<Page> {
const { targetId } = await this._browser._session.send('Target.createTarget', { url: 'about:blank', browserContextId: this._browserContextId });
// The `background` parameter is not supported by the headless shell or Android.
const background = this._browser.options.originalLaunchOptions?.createPagesInBackground && this._browser.options.headful && this._browser.options.name !== 'clank' ? true : undefined;
const { targetId } = await this._browser._session.send('Target.createTarget', { url: 'about:blank', browserContextId: this._browserContextId, background });
return this._browser._crPages.get(targetId)!._page;
}

Expand Down
8 changes: 8 additions & 0 deletions packages/playwright-core/types/types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23283,6 +23283,14 @@ export interface LaunchOptions {
*/
chromiumSandbox?: boolean;

/**
* When set to `true`, new pages are created in the background, so that the headed browser window does not activate
* and steal the OS focus from the user. Pages still behave as focused ones. Use
* [page.bringToFront()](https://playwright.dev/docs/api/class-page#page-bring-to-front) to activate the browser
* window when needed. Currently only implemented for headed Chromium. Defaults to `false`.
*/
createPagesInBackground?: boolean;

/**
* If specified, accepted downloads are downloaded into this directory. Otherwise, temporary directory is created and
* is deleted when browser is closed. In either case, the downloads are deleted when the browser context they were
Expand Down
1 change: 1 addition & 0 deletions packages/protocol/spec/mixins.yml
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ LaunchOptions:
tracesDir: string?
artifactsDir: string?
chromiumSandbox: boolean?
createPagesInBackground: boolean?
firefoxUserPrefs: json?
cdpPort: int?

Expand Down
4 changes: 4 additions & 0 deletions packages/protocol/src/channels.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1838,6 +1838,7 @@ export type BrowserTypeLaunchParams = {
tracesDir?: string,
artifactsDir?: string,
chromiumSandbox?: boolean,
createPagesInBackground?: boolean,
firefoxUserPrefs?: any,
cdpPort?: number,
slowMo?: number,
Expand All @@ -1863,6 +1864,7 @@ export type BrowserTypeLaunchOptions = {
tracesDir?: string,
artifactsDir?: string,
chromiumSandbox?: boolean,
createPagesInBackground?: boolean,
firefoxUserPrefs?: any,
cdpPort?: number,
slowMo?: number,
Expand Down Expand Up @@ -1892,6 +1894,7 @@ export type BrowserTypeLaunchPersistentContextParams = {
tracesDir?: string,
artifactsDir?: string,
chromiumSandbox?: boolean,
createPagesInBackground?: boolean,
firefoxUserPrefs?: any,
cdpPort?: number,
noDefaultViewport?: boolean,
Expand Down Expand Up @@ -1980,6 +1983,7 @@ export type BrowserTypeLaunchPersistentContextOptions = {
tracesDir?: string,
artifactsDir?: string,
chromiumSandbox?: boolean,
createPagesInBackground?: boolean,
firefoxUserPrefs?: any,
cdpPort?: number,
noDefaultViewport?: boolean,
Expand Down
24 changes: 24 additions & 0 deletions tests/library/headful.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,30 @@ it('Page.bringToFront should work', async ({ browser }) => {
await page2.close();
});

it('pages created in background should be focused and interactable', {
annotation: { type: 'issue', description: 'https://github.com/microsoft/playwright/issues/4822' },
}, async ({ browserType }) => {
// With createPagesInBackground, pages do not activate the browser window;
// emulated focus should make them behave as foreground.
const browser = await browserType.launch({ createPagesInBackground: true });
const page1 = await browser.newPage();
await page1.setContent('<input id=i>');
const page2 = await browser.newPage();
await page2.setContent('<input id=i>');

expect(await page1.evaluate('document.visibilityState')).toBe('visible');
expect(await page2.evaluate('document.visibilityState')).toBe('visible');
expect(await page1.evaluate('document.hasFocus()')).toBe(true);
expect(await page2.evaluate('document.hasFocus()')).toBe(true);

await page1.fill('#i', 'page1');
await page2.fill('#i', 'page2');
expect(await page1.inputValue('#i')).toBe('page1');
expect(await page2.inputValue('#i')).toBe('page2');

await browser.close();
});

it('should click in OOPIF', async ({ browserName, launchPersistent, server }) => {
server.setRoute('/empty.html', (req, res) => {
res.writeHead(200, { 'Content-Type': 'text/html' });
Expand Down