Skip to content

Commit

Permalink
fix(electron): stall node while browser is starting
Browse files Browse the repository at this point in the history
  • Loading branch information
pavelfeldman committed Nov 15, 2022
1 parent 6258ed5 commit 6ba0166
Show file tree
Hide file tree
Showing 5 changed files with 91 additions and 43 deletions.
39 changes: 2 additions & 37 deletions packages/playwright-core/src/server/chromium/chromium.ts
Expand Up @@ -48,6 +48,7 @@ import https from 'https';
import { registry } from '../registry';
import { ManualPromise } from '../../utils/manualPromise';
import { validateBrowserContextOptions } from '../browserContext';
import { chromiumSwitches } from './chromiumSwitches';

const ARTIFACTS_FOLDER = path.join(os.tmpdir(), 'playwright-artifacts-');

Expand Down Expand Up @@ -282,7 +283,7 @@ export class Chromium extends BrowserType {
throw new Error('Playwright manages remote debugging connection itself.');
if (args.find(arg => !arg.startsWith('-')))
throw new Error('Arguments can not specify page to be opened');
const chromeArguments = [...DEFAULT_ARGS];
const chromeArguments = [...chromiumSwitches];

// See https://github.com/microsoft/playwright/issues/7362
if (os.platform() === 'darwin')
Expand Down Expand Up @@ -325,42 +326,6 @@ export class Chromium extends BrowserType {
}
}

export const DEFAULT_ARGS = [
'--disable-field-trial-config', // https://source.chromium.org/chromium/chromium/src/+/main:testing/variations/README.md
'--disable-background-networking',
'--enable-features=NetworkService,NetworkServiceInProcess',
'--disable-background-timer-throttling',
'--disable-backgrounding-occluded-windows',
'--disable-back-forward-cache', // Avoids surprises like main request not being intercepted during page.goBack().
'--disable-breakpad',
'--disable-client-side-phishing-detection',
'--disable-component-extensions-with-background-pages',
'--disable-component-update', // Avoids unneeded network activity after startup.
'--no-default-browser-check',
'--disable-default-apps',
'--disable-dev-shm-usage',
'--disable-extensions',
// AvoidUnnecessaryBeforeUnloadCheckSync - https://github.com/microsoft/playwright/issues/14047
// Translate - https://github.com/microsoft/playwright/issues/16126
'--disable-features=ImprovedCookieControls,LazyFrameLoading,GlobalMediaControls,DestroyProfileOnBrowserClose,MediaRouter,DialMediaRouteProvider,AcceptCHFrame,AutoExpandDetailsElement,CertificateTransparencyComponentUpdater,AvoidUnnecessaryBeforeUnloadCheckSync,Translate',
'--allow-pre-commit-input',
'--disable-hang-monitor',
'--disable-ipc-flooding-protection',
'--disable-popup-blocking',
'--disable-prompt-on-repost',
'--disable-renderer-backgrounding',
'--disable-sync',
'--force-color-profile=srgb',
'--metrics-recording-only',
'--no-first-run',
'--enable-automation',
'--password-store=basic',
'--use-mock-keychain',
// See https://chromium-review.googlesource.com/c/chromium/src/+/2436773
'--no-service-autorun',
'--export-tagged-pdf'
];

async function urlToWSEndpoint(progress: Progress, endpointURL: string) {
if (endpointURL.startsWith('ws'))
return endpointURL;
Expand Down
54 changes: 54 additions & 0 deletions packages/playwright-core/src/server/chromium/chromiumSwitches.ts
@@ -0,0 +1,54 @@
/**
* Copyright 2017 Google Inc. All rights reserved.
* Modifications copyright (c) Microsoft Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

// No dependencies as it is used from the Electron loader.

export const chromiumSwitches = [
'--disable-field-trial-config', // https://source.chromium.org/chromium/chromium/src/+/main:testing/variations/README.md
'--disable-background-networking',
'--enable-features=NetworkService,NetworkServiceInProcess',
'--disable-background-timer-throttling',
'--disable-backgrounding-occluded-windows',
'--disable-back-forward-cache', // Avoids surprises like main request not being intercepted during page.goBack().
'--disable-breakpad',
'--disable-client-side-phishing-detection',
'--disable-component-extensions-with-background-pages',
'--disable-component-update', // Avoids unneeded network activity after startup.
'--no-default-browser-check',
'--disable-default-apps',
'--disable-dev-shm-usage',
'--disable-extensions',
// AvoidUnnecessaryBeforeUnloadCheckSync - https://github.com/microsoft/playwright/issues/14047
// Translate - https://github.com/microsoft/playwright/issues/16126
'--disable-features=ImprovedCookieControls,LazyFrameLoading,GlobalMediaControls,DestroyProfileOnBrowserClose,MediaRouter,DialMediaRouteProvider,AcceptCHFrame,AutoExpandDetailsElement,CertificateTransparencyComponentUpdater,AvoidUnnecessaryBeforeUnloadCheckSync,Translate',
'--allow-pre-commit-input',
'--disable-hang-monitor',
'--disable-ipc-flooding-protection',
'--disable-popup-blocking',
'--disable-prompt-on-repost',
'--disable-renderer-backgrounding',
'--disable-sync',
'--force-color-profile=srgb',
'--metrics-recording-only',
'--no-first-run',
'--enable-automation',
'--password-store=basic',
'--use-mock-keychain',
// See https://chromium-review.googlesource.com/c/chromium/src/+/2436773
'--no-service-autorun',
'--export-tagged-pdf'
];
3 changes: 2 additions & 1 deletion packages/playwright-core/src/server/electron/electron.ts
Expand Up @@ -80,6 +80,7 @@ export class ElectronApplication extends SdkObject {
await electronHandle.evaluate(({ app }) => app.quit());
});
this._nodeSession.send('Runtime.enable', {}).catch(e => {});
this._nodeSession.send('Runtime.evaluate', { expression: '__playwright_run()' });
}

process(): childProcess.ChildProcess {
Expand Down Expand Up @@ -125,7 +126,7 @@ export class Electron extends SdkObject {
controller.setLogName('browser');
return controller.run(async progress => {
let app: ElectronApplication | undefined = undefined;
const electronArguments = [...args, '--inspect=0', '--remote-debugging-port=0'];
const electronArguments = [require.resolve('./loader'), options.cwd || process.cwd(), ...args, '--inspect=0', '--remote-debugging-port=0'];

if (os.platform() === 'linux') {
const runningAsRoot = process.geteuid && process.geteuid() === 0;
Expand Down
31 changes: 31 additions & 0 deletions packages/playwright-core/src/server/electron/loader.ts
@@ -0,0 +1,31 @@
/**
* Copyright (c) Microsoft Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

const { app } = require("electron");
const path = require('path');
const { chromiumSwitches } = require('../chromium/chromiumSwitches');

const appPath = path.resolve(process.argv[2], process.argv[3]);

for (const arg of chromiumSwitches) {
const match = arg.match(/--([^=]*)=?(.*)/)!;
app.commandLine.appendSwitch(match[1], match[2]);
app.getAppPath = () => path.dirname(appPath);
}

(globalThis as any).__playwright_run = () => {
require(appPath);
};
7 changes: 2 additions & 5 deletions tests/electron/electron-app.spec.ts
Expand Up @@ -131,32 +131,29 @@ test('should create page for browser view', async ({ playwright }) => {
const app = await playwright._electron.launch({
args: [path.join(__dirname, 'electron-window-app.js')],
});
const browserViewPagePromise = app.waitForEvent('window');
await app.evaluate(async electron => {
const window = electron.BrowserWindow.getAllWindows()[0];
const view = new electron.BrowserView();
window.addBrowserView(view);
await view.webContents.loadURL('about:blank');
view.setBounds({ x: 0, y: 0, width: 256, height: 256 });
});
await browserViewPagePromise;
expect(app.windows()).toHaveLength(2);
await expect.poll(() => app.windows().length).toBe(2);
await app.close();
});

test('should return same browser window for browser view pages', async ({ playwright }) => {
const app = await playwright._electron.launch({
args: [path.join(__dirname, 'electron-window-app.js')],
});
const browserViewPagePromise = app.waitForEvent('window');
await app.evaluate(async electron => {
const window = electron.BrowserWindow.getAllWindows()[0];
const view = new electron.BrowserView();
window.addBrowserView(view);
await view.webContents.loadURL('about:blank');
view.setBounds({ x: 0, y: 0, width: 256, height: 256 });
});
await browserViewPagePromise;
await expect.poll(() => app.windows().length).toBe(2);
const [firstWindowId, secondWindowId] = await Promise.all(
app.windows().map(async page => {
const bwHandle = await app.browserWindow(page);
Expand Down

0 comments on commit 6ba0166

Please sign in to comment.