summaryrefslogtreecommitdiffstats
path: root/remote/test/puppeteer/packages/puppeteer-core/src/node/FirefoxLauncher.ts
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
commit26a029d407be480d791972afb5975cf62c9360a6 (patch)
treef435a8308119effd964b339f76abb83a57c29483 /remote/test/puppeteer/packages/puppeteer-core/src/node/FirefoxLauncher.ts
parentInitial commit. (diff)
downloadfirefox-26a029d407be480d791972afb5975cf62c9360a6.tar.xz
firefox-26a029d407be480d791972afb5975cf62c9360a6.zip
Adding upstream version 124.0.1.upstream/124.0.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'remote/test/puppeteer/packages/puppeteer-core/src/node/FirefoxLauncher.ts')
-rw-r--r--remote/test/puppeteer/packages/puppeteer-core/src/node/FirefoxLauncher.ts242
1 files changed, 242 insertions, 0 deletions
diff --git a/remote/test/puppeteer/packages/puppeteer-core/src/node/FirefoxLauncher.ts b/remote/test/puppeteer/packages/puppeteer-core/src/node/FirefoxLauncher.ts
new file mode 100644
index 0000000000..eb4f375fc7
--- /dev/null
+++ b/remote/test/puppeteer/packages/puppeteer-core/src/node/FirefoxLauncher.ts
@@ -0,0 +1,242 @@
+/**
+ * @license
+ * Copyright 2023 Google Inc.
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+import fs from 'fs';
+import {rename, unlink, mkdtemp} from 'fs/promises';
+import os from 'os';
+import path from 'path';
+
+import {
+ Browser as SupportedBrowsers,
+ createProfile,
+ Cache,
+ detectBrowserPlatform,
+ Browser,
+} from '@puppeteer/browsers';
+
+import {debugError} from '../common/util.js';
+import {assert} from '../util/assert.js';
+
+import type {
+ BrowserLaunchArgumentOptions,
+ PuppeteerNodeLaunchOptions,
+} from './LaunchOptions.js';
+import {ProductLauncher, type ResolvedLaunchArgs} from './ProductLauncher.js';
+import type {PuppeteerNode} from './PuppeteerNode.js';
+import {rm} from './util/fs.js';
+
+/**
+ * @internal
+ */
+export class FirefoxLauncher extends ProductLauncher {
+ constructor(puppeteer: PuppeteerNode) {
+ super(puppeteer, 'firefox');
+ }
+
+ static getPreferences(
+ extraPrefsFirefox?: Record<string, unknown>,
+ protocol?: 'cdp' | 'webDriverBiDi'
+ ): Record<string, unknown> {
+ return {
+ ...extraPrefsFirefox,
+ ...(protocol === 'webDriverBiDi'
+ ? {}
+ : {
+ // Do not close the window when the last tab gets closed
+ 'browser.tabs.closeWindowWithLastTab': false,
+ // Temporarily force disable BFCache in parent (https://bit.ly/bug-1732263)
+ 'fission.bfcacheInParent': false,
+ }),
+ // Force all web content to use a single content process. TODO: remove
+ // this once Firefox supports mouse event dispatch from the main frame
+ // context. Once this happens, webContentIsolationStrategy should only
+ // be set for CDP. See
+ // https://bugzilla.mozilla.org/show_bug.cgi?id=1773393
+ 'fission.webContentIsolationStrategy': 0,
+ };
+ }
+
+ /**
+ * @internal
+ */
+ override async computeLaunchArguments(
+ options: PuppeteerNodeLaunchOptions = {}
+ ): Promise<ResolvedLaunchArgs> {
+ const {
+ ignoreDefaultArgs = false,
+ args = [],
+ executablePath,
+ pipe = false,
+ extraPrefsFirefox = {},
+ debuggingPort = null,
+ } = options;
+
+ const firefoxArguments = [];
+ if (!ignoreDefaultArgs) {
+ firefoxArguments.push(...this.defaultArgs(options));
+ } else if (Array.isArray(ignoreDefaultArgs)) {
+ firefoxArguments.push(
+ ...this.defaultArgs(options).filter(arg => {
+ return !ignoreDefaultArgs.includes(arg);
+ })
+ );
+ } else {
+ firefoxArguments.push(...args);
+ }
+
+ if (
+ !firefoxArguments.some(argument => {
+ return argument.startsWith('--remote-debugging-');
+ })
+ ) {
+ if (pipe) {
+ assert(
+ debuggingPort === null,
+ 'Browser should be launched with either pipe or debugging port - not both.'
+ );
+ }
+ firefoxArguments.push(`--remote-debugging-port=${debuggingPort || 0}`);
+ }
+
+ let userDataDir: string | undefined;
+ let isTempUserDataDir = true;
+
+ // Check for the profile argument, which will always be set even
+ // with a custom directory specified via the userDataDir option.
+ const profileArgIndex = firefoxArguments.findIndex(arg => {
+ return ['-profile', '--profile'].includes(arg);
+ });
+
+ if (profileArgIndex !== -1) {
+ userDataDir = firefoxArguments[profileArgIndex + 1];
+ if (!userDataDir || !fs.existsSync(userDataDir)) {
+ throw new Error(`Firefox profile not found at '${userDataDir}'`);
+ }
+
+ // When using a custom Firefox profile it needs to be populated
+ // with required preferences.
+ isTempUserDataDir = false;
+ } else {
+ userDataDir = await mkdtemp(this.getProfilePath());
+ firefoxArguments.push('--profile');
+ firefoxArguments.push(userDataDir);
+ }
+
+ await createProfile(SupportedBrowsers.FIREFOX, {
+ path: userDataDir,
+ preferences: FirefoxLauncher.getPreferences(
+ extraPrefsFirefox,
+ options.protocol
+ ),
+ });
+
+ let firefoxExecutable: string;
+ if (this.puppeteer._isPuppeteerCore || executablePath) {
+ assert(
+ executablePath,
+ `An \`executablePath\` must be specified for \`puppeteer-core\``
+ );
+ firefoxExecutable = executablePath;
+ } else {
+ firefoxExecutable = this.executablePath();
+ }
+
+ return {
+ isTempUserDataDir,
+ userDataDir,
+ args: firefoxArguments,
+ executablePath: firefoxExecutable,
+ };
+ }
+
+ /**
+ * @internal
+ */
+ override async cleanUserDataDir(
+ userDataDir: string,
+ opts: {isTemp: boolean}
+ ): Promise<void> {
+ if (opts.isTemp) {
+ try {
+ await rm(userDataDir);
+ } catch (error) {
+ debugError(error);
+ throw error;
+ }
+ } else {
+ try {
+ // When an existing user profile has been used remove the user
+ // preferences file and restore possibly backuped preferences.
+ await unlink(path.join(userDataDir, 'user.js'));
+
+ const prefsBackupPath = path.join(userDataDir, 'prefs.js.puppeteer');
+ if (fs.existsSync(prefsBackupPath)) {
+ const prefsPath = path.join(userDataDir, 'prefs.js');
+ await unlink(prefsPath);
+ await rename(prefsBackupPath, prefsPath);
+ }
+ } catch (error) {
+ debugError(error);
+ }
+ }
+ }
+
+ override executablePath(): string {
+ // replace 'latest' placeholder with actual downloaded revision
+ if (this.puppeteer.browserRevision === 'latest') {
+ const cache = new Cache(this.puppeteer.defaultDownloadPath!);
+ const installedFirefox = cache.getInstalledBrowsers().find(browser => {
+ return (
+ browser.platform === detectBrowserPlatform() &&
+ browser.browser === Browser.FIREFOX
+ );
+ });
+ if (installedFirefox) {
+ this.actualBrowserRevision = installedFirefox.buildId;
+ }
+ }
+ return this.resolveExecutablePath();
+ }
+
+ override defaultArgs(options: BrowserLaunchArgumentOptions = {}): string[] {
+ const {
+ devtools = false,
+ headless = !devtools,
+ args = [],
+ userDataDir = null,
+ } = options;
+
+ const firefoxArguments = ['--no-remote'];
+
+ switch (os.platform()) {
+ case 'darwin':
+ firefoxArguments.push('--foreground');
+ break;
+ case 'win32':
+ firefoxArguments.push('--wait-for-browser');
+ break;
+ }
+ if (userDataDir) {
+ firefoxArguments.push('--profile');
+ firefoxArguments.push(userDataDir);
+ }
+ if (headless) {
+ firefoxArguments.push('--headless');
+ }
+ if (devtools) {
+ firefoxArguments.push('--devtools');
+ }
+ if (
+ args.every(arg => {
+ return arg.startsWith('-');
+ })
+ ) {
+ firefoxArguments.push('about:blank');
+ }
+ firefoxArguments.push(...args);
+ return firefoxArguments;
+ }
+}