UNPKG

puppeteer-core

Version:

A high-level API to control headless Chrome over the DevTools Protocol

246 lines 10.7 kB
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) { if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); }; var _ChromeLauncher_instances, _ChromeLauncher_executablePathForChannel; import { accessSync } from 'fs'; import { mkdtemp } from 'fs/promises'; import os from 'os'; import path from 'path'; import { assert } from '../util/assert.js'; import { BrowserRunner } from './BrowserRunner.js'; import { CDPBrowser } from '../common/Browser.js'; import { ProductLauncher } from './ProductLauncher.js'; /** * @internal */ export class ChromeLauncher extends ProductLauncher { constructor(puppeteer) { super(puppeteer, 'chrome'); _ChromeLauncher_instances.add(this); } async launch(options = {}) { const { ignoreDefaultArgs = false, args = [], dumpio = false, channel, executablePath, pipe = false, env = process.env, handleSIGINT = true, handleSIGTERM = true, handleSIGHUP = true, ignoreHTTPSErrors = false, defaultViewport = { width: 800, height: 600 }, slowMo = 0, timeout = 30000, waitForInitialPage = true, debuggingPort, protocol, } = options; const chromeArguments = []; if (!ignoreDefaultArgs) { chromeArguments.push(...this.defaultArgs(options)); } else if (Array.isArray(ignoreDefaultArgs)) { chromeArguments.push(...this.defaultArgs(options).filter(arg => { return !ignoreDefaultArgs.includes(arg); })); } else { chromeArguments.push(...args); } if (!chromeArguments.some(argument => { return argument.startsWith('--remote-debugging-'); })) { if (pipe) { assert(!debuggingPort, 'Browser should be launched with either pipe or debugging port - not both.'); chromeArguments.push('--remote-debugging-pipe'); } else { chromeArguments.push(`--remote-debugging-port=${debuggingPort || 0}`); } } let isTempUserDataDir = false; // Check for the user data dir argument, which will always be set even // with a custom directory specified via the userDataDir option. let userDataDirIndex = chromeArguments.findIndex(arg => { return arg.startsWith('--user-data-dir'); }); if (userDataDirIndex < 0) { isTempUserDataDir = true; chromeArguments.push(`--user-data-dir=${await mkdtemp(this.getProfilePath())}`); userDataDirIndex = chromeArguments.length - 1; } const userDataDir = chromeArguments[userDataDirIndex].split('=', 2)[1]; assert(typeof userDataDir === 'string', '`--user-data-dir` is malformed'); let chromeExecutable = executablePath; if (!chromeExecutable) { assert(channel || !this.puppeteer._isPuppeteerCore, `An \`executablePath\` or \`channel\` must be specified for \`puppeteer-core\``); chromeExecutable = this.executablePath(channel); } const usePipe = chromeArguments.includes('--remote-debugging-pipe'); const runner = new BrowserRunner(this.product, chromeExecutable, chromeArguments, userDataDir, isTempUserDataDir); runner.start({ handleSIGHUP, handleSIGTERM, handleSIGINT, dumpio, env, pipe: usePipe, }); let browser; try { const connection = await runner.setupConnection({ usePipe, timeout, slowMo, preferredRevision: this.puppeteer.browserRevision, }); if (protocol === 'webDriverBiDi') { try { const BiDi = await import('../common/bidi/bidi.js'); const bidiConnection = await BiDi.connectBidiOverCDP(connection); browser = await BiDi.Browser.create({ connection: bidiConnection, closeCallback: runner.close.bind(runner), process: runner.proc, }); } catch (error) { runner.kill(); throw error; } return browser; } browser = await CDPBrowser._create(this.product, connection, [], ignoreHTTPSErrors, defaultViewport, runner.proc, runner.close.bind(runner), options.targetFilter); } catch (error) { runner.kill(); throw error; } if (waitForInitialPage) { try { await browser.waitForTarget(t => { return t.type() === 'page'; }, { timeout }); } catch (error) { await browser.close(); throw error; } } return browser; } defaultArgs(options = {}) { // See https://github.com/GoogleChrome/chrome-launcher/blob/main/docs/chrome-flags-for-tools.md const chromeArguments = [ '--allow-pre-commit-input', '--disable-background-networking', '--disable-background-timer-throttling', '--disable-backgrounding-occluded-windows', '--disable-breakpad', '--disable-client-side-phishing-detection', '--disable-component-extensions-with-background-pages', '--disable-component-update', '--disable-default-apps', '--disable-dev-shm-usage', '--disable-extensions', // AcceptCHFrame disabled because of crbug.com/1348106. '--disable-features=Translate,BackForwardCache,AcceptCHFrame,MediaRouter,OptimizationHints', '--disable-hang-monitor', '--disable-ipc-flooding-protection', '--disable-popup-blocking', '--disable-prompt-on-repost', '--disable-renderer-backgrounding', '--disable-sync', '--enable-automation', // TODO(sadym): remove '--enable-blink-features=IdleDetection' once // IdleDetection is turned on by default. '--enable-blink-features=IdleDetection', '--enable-features=NetworkServiceInProcess2', '--export-tagged-pdf', '--force-color-profile=srgb', '--metrics-recording-only', '--no-first-run', '--password-store=basic', '--use-mock-keychain', ]; const { devtools = false, headless = !devtools, args = [], userDataDir, } = options; if (userDataDir) { chromeArguments.push(`--user-data-dir=${path.resolve(userDataDir)}`); } if (devtools) { chromeArguments.push('--auto-open-devtools-for-tabs'); } if (headless) { chromeArguments.push(headless === 'new' ? '--headless=new' : '--headless', '--hide-scrollbars', '--mute-audio'); } if (args.every(arg => { return arg.startsWith('-'); })) { chromeArguments.push('about:blank'); } chromeArguments.push(...args); return chromeArguments; } executablePath(channel) { if (channel) { return __classPrivateFieldGet(this, _ChromeLauncher_instances, "m", _ChromeLauncher_executablePathForChannel).call(this, channel); } else { return this.resolveExecutablePath(); } } } _ChromeLauncher_instances = new WeakSet(), _ChromeLauncher_executablePathForChannel = function _ChromeLauncher_executablePathForChannel(channel) { const platform = os.platform(); let chromePath; switch (platform) { case 'win32': switch (channel) { case 'chrome': chromePath = `${process.env['PROGRAMFILES']}\\Google\\Chrome\\Application\\chrome.exe`; break; case 'chrome-beta': chromePath = `${process.env['PROGRAMFILES']}\\Google\\Chrome Beta\\Application\\chrome.exe`; break; case 'chrome-canary': chromePath = `${process.env['PROGRAMFILES']}\\Google\\Chrome SxS\\Application\\chrome.exe`; break; case 'chrome-dev': chromePath = `${process.env['PROGRAMFILES']}\\Google\\Chrome Dev\\Application\\chrome.exe`; break; } break; case 'darwin': switch (channel) { case 'chrome': chromePath = '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome'; break; case 'chrome-beta': chromePath = '/Applications/Google Chrome Beta.app/Contents/MacOS/Google Chrome Beta'; break; case 'chrome-canary': chromePath = '/Applications/Google Chrome Canary.app/Contents/MacOS/Google Chrome Canary'; break; case 'chrome-dev': chromePath = '/Applications/Google Chrome Dev.app/Contents/MacOS/Google Chrome Dev'; break; } break; case 'linux': switch (channel) { case 'chrome': chromePath = '/opt/google/chrome/chrome'; break; case 'chrome-beta': chromePath = '/opt/google/chrome-beta/chrome'; break; case 'chrome-dev': chromePath = '/opt/google/chrome-unstable/chrome'; break; } break; } if (!chromePath) { throw new Error(`Unable to detect browser executable path for '${channel}' on ${platform}.`); } // Check if Chrome exists and is accessible. try { accessSync(chromePath); } catch (error) { throw new Error(`Could not find Google Chrome executable for channel '${channel}' at '${chromePath}'.`); } return chromePath; }; //# sourceMappingURL=ChromeLauncher.js.map