diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 45c862d89d1..c732a56bef2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -150,12 +150,12 @@ jobs: PUPPETEER_SKIP_DOWNLOAD: true - name: Build packages run: npm run build --workspace @puppeteer-test/test - - name: Setup cache for Chromium binary + - name: Setup cache for Chrome binary uses: actions/cache@v3 with: path: ~/.cache/puppeteer/chrome - key: ${{ runner.os }}-chromium-${{ hashFiles('packages/puppeteer-core/src/revisions.ts') }}-${{ hashFiles('packages/puppeteer/src/node/install.ts') }} - - name: Install Chromium + key: ${{ runner.os }}-Chrome-${{ hashFiles('packages/puppeteer-core/src/revisions.ts') }}-${{ hashFiles('packages/puppeteer/src/node/install.ts') }} + - name: Install Chrome run: npm run postinstall - name: Tests types run: npm run test-types diff --git a/.github/workflows/tot-ci.yml b/.github/workflows/tot-ci.yml deleted file mode 100644 index 5eb8b2ff043..00000000000 --- a/.github/workflows/tot-ci.yml +++ /dev/null @@ -1,54 +0,0 @@ -name: ToT CI - -# Checks Puppeteer against the latest ToT build of Chromium. -# Declare default permissions as read only. -permissions: read-all - -on: - workflow_dispatch: - schedule: - # * is a special character in YAML so you have to quote this string - # Supposed to be every day at 8 am (UTC). - - cron: '0 8 * * *' - -# TODO: how to make install & build steps re-usable across jobs. -# Currently, the install step is duplicated but should be the same for all jobs. - -jobs: - ci: - name: ${{ matrix.suite }} tests - runs-on: ubuntu-latest - strategy: - fail-fast: false - matrix: - suite: - - chrome-headless - - chrome-headful - - chrome-new-headless - steps: - - name: Check out repository - uses: actions/checkout@v3.0.2 - - name: Set up Node.js - uses: actions/setup-node@v3.5.1 - with: - cache: npm - node-version: lts/* - - name: Install dependencies - run: npm ci - env: - PUPPETEER_SKIP_DOWNLOAD: true - - name: Install linux dependencies. - run: sudo apt-get install xvfb - - name: Build packages - run: npm run build - - name: Get latest revision - run: | - REV=$(node tools/check_availability.js -p linux) - cat packages/puppeteer-core/src/revisions.ts | sed "s/[0-9]\{6,\}/$REV/" > packages/puppeteer-core/src/revisions.ts.replaced - mv packages/puppeteer-core/src/revisions.ts.replaced packages/puppeteer-core/src/revisions.ts - - name: Rebuild `puppeteer-core` - run: npm run build --workspace puppeteer-core - - name: Install Chrome - run: npm run postinstall --workspace puppeteer - - name: Run tests - run: xvfb-run --auto-servernum npm run test -- --test-suite ${{ matrix.suite }} diff --git a/README.md b/README.md index 856e4b0503d..a7df543c828 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ > [DevTools Protocol](https://chromedevtools.github.io/devtools-protocol/). > Puppeteer runs in > [headless](https://developer.chrome.com/articles/new-headless/) -> mode by default, but can be configured to run in full (non-headless) +> mode by default, but can be configured to run in full ("headful") > Chrome/Chromium. #### What can I do? @@ -46,7 +46,7 @@ pnpm i puppeteer ``` When you install Puppeteer, it automatically downloads a recent version of -Chromium (~170MB macOS, ~282MB Linux, ~280MB Windows) that is [guaranteed to +[Chrome for Testing](https://goo.gle/chrome-for-testing) (~170MB macOS, ~282MB Linux, ~280MB Windows) that is [guaranteed to work](https://pptr.dev/faq#q-why-doesnt-puppeteer-vxxx-work-with-chromium-vyyy) with Puppeteer. The browser is downloaded to the `$HOME/.cache/puppeteer` folder by default (starting with Puppeteer v19.0.0). @@ -94,14 +94,14 @@ Every release since v1.7.0 we publish two packages: - [`puppeteer-core`](https://www.npmjs.com/package/puppeteer-core) `puppeteer` is a _product_ for browser automation. When installed, it downloads -a version of Chromium, which it then drives using `puppeteer-core`. Being an +a version of Chrome, which it then drives using `puppeteer-core`. Being an end-user product, `puppeteer` automates several workflows using reasonable defaults [that can be customized](https://pptr.dev/guides/configuration). `puppeteer-core` is a _library_ to help drive anything that supports DevTools protocol. Being a library, `puppeteer-core` is fully driven through its programmatic interface implying no defaults are assumed and `puppeteer-core` -will not download Chromium when installed. +will not download Chrome when installed. You should use `puppeteer-core` if you are [connecting to a remote browser](https://pptr.dev/api/puppeteer.puppeteer.connect) @@ -176,7 +176,7 @@ import puppeteer from 'puppeteer'; **1. Uses Headless mode** -By default Puppeteer launches Chromium in +By default Puppeteer launches Chrome in [old Headless mode](https://developer.chrome.com/articles/new-headless/). ```ts @@ -193,7 +193,7 @@ We recommend you try it out before the switch: const browser = await puppeteer.launch({headless: 'new'}); ``` -To launch a "headful" version of Chromium, set the +To launch a "headful" version of Chrome, set the [`headless`](https://pptr.dev/api/puppeteer.browserlaunchargumentoptions) to `false` option when launching a browser: @@ -201,9 +201,9 @@ option when launching a browser: const browser = await puppeteer.launch({headless: false}); ``` -**2. Runs a bundled version of Chromium** +**2. Runs a bundled version of Chrome** -By default, Puppeteer downloads and uses a specific version of Chromium so its +By default, Puppeteer downloads and uses a specific version of Chrome so its API is guaranteed to work out of the box. To use Puppeteer with a different version of Chrome or Chromium, pass in the executable's path when creating a `Browser` instance: diff --git a/docker/Dockerfile b/docker/Dockerfile index 16955fbca5a..d411dc955d6 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -1,7 +1,7 @@ FROM node:18 # Install latest chrome dev package and fonts to support major charsets (Chinese, Japanese, Arabic, Hebrew, Thai and a few others) -# Note: this installs the necessary libs to make the bundled version of Chromium that Puppeteer +# Note: this installs the necessary libs to make the bundled version of Chrome that Puppeteer # installs, work. RUN apt-get update \ && apt-get install -y wget gnupg \ diff --git a/docker/README.md b/docker/README.md index 8b1861e59b1..10eff5336aa 100644 --- a/docker/README.md +++ b/docker/README.md @@ -16,7 +16,7 @@ docker build -t puppeteer-chrome-linux . # `puppeteer-chrome-linux` is the name docker run -i --init --rm --cap-add=SYS_ADMIN --name puppeteer-chrome puppeteer-chrome-linux node -e "`cat test.js`" ``` -`--cap-add=SYS_ADMIN` capability is needed to enable Chromium sandbox that makes the browser more secure. Alternatively, it should be possible to start the browser binary with the `--no-sandbox` flag. +`--cap-add=SYS_ADMIN` capability is needed to enable Chrome sandbox that makes the browser more secure. Alternatively, it should be possible to start the browser binary with the `--no-sandbox` flag. ## GitHub Actions diff --git a/docs/api/index.md b/docs/api/index.md index 08fda59a0df..56fac9968b6 100644 --- a/docs/api/index.md +++ b/docs/api/index.md @@ -9,10 +9,9 @@ sidebar_label: API | Class | Description | | --------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | [AbortError](./puppeteer.aborterror.md) | AbortError is emitted whenever certain operations are terminated due to an abort request. | -| [Accessibility](./puppeteer.accessibility.md) | The Accessibility class provides methods for inspecting Chromium's accessibility tree. The accessibility tree is used by assistive technology such as [screen readers](https://en.wikipedia.org/wiki/Screen_reader) or [switches](https://en.wikipedia.org/wiki/Switch_access). | -| [Browser](./puppeteer.browser.md) | A Browser is created when Puppeteer connects to a Chromium instance, either through [PuppeteerNode.launch()](./puppeteer.puppeteernode.launch.md) or [Puppeteer.connect()](./puppeteer.puppeteer.connect.md). | +| [Accessibility](./puppeteer.accessibility.md) | The Accessibility class provides methods for inspecting the browser's accessibility tree. The accessibility tree is used by assistive technology such as [screen readers](https://en.wikipedia.org/wiki/Screen_reader) or [switches](https://en.wikipedia.org/wiki/Switch_access). | +| [Browser](./puppeteer.browser.md) | A Browser is created when Puppeteer connects to a browser instance, either through [PuppeteerNode.launch()](./puppeteer.puppeteernode.launch.md) or [Puppeteer.connect()](./puppeteer.puppeteer.connect.md). | | [BrowserContext](./puppeteer.browsercontext.md) | BrowserContexts provide a way to operate multiple independent browser sessions. When a browser is launched, it has a single BrowserContext used by default. The method [Browser.newPage](./puppeteer.browser.newpage.md) creates a page in the default browser context. | -| [BrowserFetcher](./puppeteer.browserfetcher.md) | BrowserFetcher can download and manage different versions of Chromium and Firefox. | | [CDPSession](./puppeteer.cdpsession.md) | The CDPSession instances are used to talk raw Chrome Devtools Protocol. | | [Connection](./puppeteer.connection.md) | | | [ConsoleMessage](./puppeteer.consolemessage.md) | ConsoleMessage objects are dispatched by page via the 'console' event. | @@ -32,7 +31,7 @@ sidebar_label: API | [JSHandle](./puppeteer.jshandle.md) |

Represents a reference to a JavaScript object. Instances can be created using [Page.evaluateHandle()](./puppeteer.page.evaluatehandle.md).

Handles prevent the referenced JavaScript object from being garbage-collected unless the handle is purposely [disposed](./puppeteer.jshandle.dispose.md). JSHandles are auto-disposed when their associated frame is navigated away or the parent context gets destroyed.

Handles can be used as arguments for any evaluation function such as [Page.$eval()](./puppeteer.page._eval.md), [Page.evaluate()](./puppeteer.page.evaluate.md), and [Page.evaluateHandle()](./puppeteer.page.evaluatehandle.md). They are resolved to their referenced object.

| | [Keyboard](./puppeteer.keyboard.md) | Keyboard provides an api for managing a virtual keyboard. The high level api is [Keyboard.type()](./puppeteer.keyboard.type.md), which takes raw characters and generates proper keydown, keypress/input, and keyup events on your page. | | [Mouse](./puppeteer.mouse.md) | The Mouse class operates in main-frame CSS pixels relative to the top-left corner of the viewport. | -| [Page](./puppeteer.page.md) |

Page provides methods to interact with a single tab or [extension background page](https://developer.chrome.com/extensions/background_pages) in Chromium.

:::note

One Browser instance might have multiple Page instances.

:::

| +| [Page](./puppeteer.page.md) |

Page provides methods to interact with a single tab or [extension background page](https://developer.chrome.com/extensions/background_pages) in the browser.

:::note

One Browser instance might have multiple Page instances.

:::

| | [ProductLauncher](./puppeteer.productlauncher.md) | Describes a launcher - a class that is able to create and launch a browser instance. | | [ProtocolError](./puppeteer.protocolerror.md) | ProtocolError is emitted whenever there is an error from the protocol. | | [Puppeteer](./puppeteer.puppeteer.md) |

The main Puppeteer class.

IMPORTANT: if you are using Puppeteer in a Node environment, you will get an instance of [PuppeteerNode](./puppeteer.puppeteernode.md) when you import or require puppeteer. That class extends Puppeteer, so has all the methods documented below as well as all that are defined on [PuppeteerNode](./puppeteer.puppeteernode.md).

| @@ -70,8 +69,6 @@ sidebar_label: API | [BoxModel](./puppeteer.boxmodel.md) | | | [BrowserConnectOptions](./puppeteer.browserconnectoptions.md) | Generic browser options that can be passed when launching any browser or when connecting to an existing browser instance. | | [BrowserContextOptions](./puppeteer.browsercontextoptions.md) | BrowserContext options. | -| [BrowserFetcherOptions](./puppeteer.browserfetcheroptions.md) | | -| [BrowserFetcherRevisionInfo](./puppeteer.browserfetcherrevisioninfo.md) | | | [BrowserLaunchArgumentOptions](./puppeteer.browserlaunchargumentoptions.md) | Launcher options that only apply to Chrome. | | [CDPSessionOnMessageObject](./puppeteer.cdpsessiononmessageobject.md) | | | [ClickOptions](./puppeteer.clickoptions.md) | | @@ -86,7 +83,6 @@ sidebar_label: API | [CSSCoverageOptions](./puppeteer.csscoverageoptions.md) | Set of configurable options for CSS coverage. | | [CustomQueryHandler](./puppeteer.customqueryhandler.md) | | | [Device](./puppeteer.device.md) | | -| [ExperimentsConfiguration](./puppeteer.experimentsconfiguration.md) |

Defines experiment options for Puppeteer.

See individual properties for more information.

| | [FrameAddScriptTagOptions](./puppeteer.frameaddscripttagoptions.md) | | | [FrameAddStyleTagOptions](./puppeteer.frameaddstyletagoptions.md) | | | [FrameWaitForFunctionOptions](./puppeteer.framewaitforfunctionoptions.md) | | @@ -129,7 +125,6 @@ sidebar_label: API | Variable | Description | | --------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- | | [connect](./puppeteer.connect.md) | | -| [createBrowserFetcher](./puppeteer.createbrowserfetcher.md) | | | [DEFAULT_INTERCEPT_RESOLUTION_PRIORITY](./puppeteer.default_intercept_resolution_priority.md) | The default cooperative request interception resolution priority | | [defaultArgs](./puppeteer.defaultargs.md) | | | [devices](./puppeteer.devices.md) | | @@ -157,6 +152,7 @@ sidebar_label: API | [EvaluateFunc](./puppeteer.evaluatefunc.md) | | | [EvaluateFuncWith](./puppeteer.evaluatefuncwith.md) | | | [EventType](./puppeteer.eventtype.md) | | +| [ExperimentsConfiguration](./puppeteer.experimentsconfiguration.md) |

Defines experiment options for Puppeteer.

See individual properties for more information.

| | [FlattenHandle](./puppeteer.flattenhandle.md) | | | [HandleFor](./puppeteer.handlefor.md) | | | [HandleOr](./puppeteer.handleor.md) | | @@ -169,7 +165,6 @@ sidebar_label: API | [NodeFor](./puppeteer.nodefor.md) | | | [PaperFormat](./puppeteer.paperformat.md) | All the valid paper format types when printing a PDF. | | [Permission](./puppeteer.permission.md) | | -| [Platform](./puppeteer.platform.md) | Supported platforms. | | [Product](./puppeteer.product.md) | Supported products. | | [ProtocolLifeCycleEvent](./puppeteer.protocollifecycleevent.md) | | | [PuppeteerLifeCycleEvent](./puppeteer.puppeteerlifecycleevent.md) | | diff --git a/docs/api/puppeteer.accessibility.md b/docs/api/puppeteer.accessibility.md index f17d1433415..542c197cc5f 100644 --- a/docs/api/puppeteer.accessibility.md +++ b/docs/api/puppeteer.accessibility.md @@ -4,7 +4,7 @@ sidebar_label: Accessibility # Accessibility class -The Accessibility class provides methods for inspecting Chromium's accessibility tree. The accessibility tree is used by assistive technology such as [screen readers](https://en.wikipedia.org/wiki/Screen_reader) or [switches](https://en.wikipedia.org/wiki/Switch_access). +The Accessibility class provides methods for inspecting the browser's accessibility tree. The accessibility tree is used by assistive technology such as [screen readers](https://en.wikipedia.org/wiki/Screen_reader) or [switches](https://en.wikipedia.org/wiki/Switch_access). #### Signature: diff --git a/docs/api/puppeteer.accessibility.snapshot.md b/docs/api/puppeteer.accessibility.snapshot.md index e2f0b6e91a5..4dd49a8d164 100644 --- a/docs/api/puppeteer.accessibility.snapshot.md +++ b/docs/api/puppeteer.accessibility.snapshot.md @@ -28,7 +28,7 @@ An AXNode object representing the snapshot. ## Remarks -**NOTE** The Chromium accessibility tree contains nodes that go unused on most platforms and by most screen readers. Puppeteer will discard them as well for an easier to process tree, unless `interestingOnly` is set to `false`. +**NOTE** The Chrome accessibility tree contains nodes that go unused on most platforms and by most screen readers. Puppeteer will discard them as well for an easier to process tree, unless `interestingOnly` is set to `false`. ## Example 1 diff --git a/docs/api/puppeteer.browser.close.md b/docs/api/puppeteer.browser.close.md index a087539853d..b7c30033e6d 100644 --- a/docs/api/puppeteer.browser.close.md +++ b/docs/api/puppeteer.browser.close.md @@ -4,7 +4,7 @@ sidebar_label: Browser.close # Browser.close() method -Closes Chromium and all of its pages (if any were opened). The [Browser](./puppeteer.browser.md) object itself is considered to be disposed and cannot be used anymore. +Closes the browser and all of its pages (if any were opened). The [Browser](./puppeteer.browser.md) object itself is considered to be disposed and cannot be used anymore. #### Signature: diff --git a/docs/api/puppeteer.browser.disconnect.md b/docs/api/puppeteer.browser.disconnect.md index 35f9a5779f1..c102c10b094 100644 --- a/docs/api/puppeteer.browser.disconnect.md +++ b/docs/api/puppeteer.browser.disconnect.md @@ -4,7 +4,7 @@ sidebar_label: Browser.disconnect # Browser.disconnect() method -Disconnects Puppeteer from the browser, but leaves the Chromium process running. After calling `disconnect`, the [Browser](./puppeteer.browser.md) object is considered disposed and cannot be used anymore. +Disconnects Puppeteer from the browser, but leaves the browser process running. After calling `disconnect`, the [Browser](./puppeteer.browser.md) object is considered disposed and cannot be used anymore. #### Signature: diff --git a/docs/api/puppeteer.browser.md b/docs/api/puppeteer.browser.md index bfee6200652..cf22ac7eaf0 100644 --- a/docs/api/puppeteer.browser.md +++ b/docs/api/puppeteer.browser.md @@ -4,7 +4,7 @@ sidebar_label: Browser # Browser class -A Browser is created when Puppeteer connects to a Chromium instance, either through [PuppeteerNode.launch()](./puppeteer.puppeteernode.launch.md) or [Puppeteer.connect()](./puppeteer.puppeteer.connect.md). +A Browser is created when Puppeteer connects to a browser instance, either through [PuppeteerNode.launch()](./puppeteer.puppeteernode.launch.md) or [Puppeteer.connect()](./puppeteer.puppeteer.connect.md). #### Signature: @@ -44,34 +44,34 @@ import puppeteer from 'puppeteer'; (async () => { const browser = await puppeteer.launch(); - // Store the endpoint to be able to reconnect to Chromium + // Store the endpoint to be able to reconnect to the browser. const browserWSEndpoint = browser.wsEndpoint(); - // Disconnect puppeteer from Chromium + // Disconnect puppeteer from the browser. browser.disconnect(); // Use the endpoint to reestablish a connection const browser2 = await puppeteer.connect({browserWSEndpoint}); - // Close Chromium + // Close the browser. await browser2.close(); })(); ``` ## Methods -| Method | Modifiers | Description | -| ---------------------------------------------------------------------------------------------- | --------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| [browserContexts()](./puppeteer.browser.browsercontexts.md) | | Returns an array of all open browser contexts. In a newly created browser, this will return a single instance of [BrowserContext](./puppeteer.browsercontext.md). | -| [close()](./puppeteer.browser.close.md) | | Closes Chromium and all of its pages (if any were opened). The [Browser](./puppeteer.browser.md) object itself is considered to be disposed and cannot be used anymore. | -| [createIncognitoBrowserContext(options)](./puppeteer.browser.createincognitobrowsercontext.md) | | Creates a new incognito browser context. This won't share cookies/cache with other browser contexts. | -| [defaultBrowserContext()](./puppeteer.browser.defaultbrowsercontext.md) | | Returns the default browser context. The default browser context cannot be closed. | -| [disconnect()](./puppeteer.browser.disconnect.md) | | Disconnects Puppeteer from the browser, but leaves the Chromium process running. After calling disconnect, the [Browser](./puppeteer.browser.md) object is considered disposed and cannot be used anymore. | -| [isConnected()](./puppeteer.browser.isconnected.md) | | Indicates that the browser is connected. | -| [newPage()](./puppeteer.browser.newpage.md) | | Promise which resolves to a new [Page](./puppeteer.page.md) object. The Page is created in a default browser context. | -| [pages()](./puppeteer.browser.pages.md) | | An array of all open pages inside the Browser. | -| [process()](./puppeteer.browser.process.md) | | The spawned browser process. Returns null if the browser instance was created with [Puppeteer.connect()](./puppeteer.puppeteer.connect.md). | -| [target()](./puppeteer.browser.target.md) | | The target associated with the browser. | -| [targets()](./puppeteer.browser.targets.md) | | All active targets inside the Browser. In case of multiple browser contexts, returns an array with all the targets in all browser contexts. | -| [userAgent()](./puppeteer.browser.useragent.md) | | The browser's original user agent. Pages can override the browser user agent with [Page.setUserAgent()](./puppeteer.page.setuseragent.md). | -| [version()](./puppeteer.browser.version.md) | | A string representing the browser name and version. | -| [waitForTarget(predicate, options)](./puppeteer.browser.waitfortarget.md) | | Searches for a target in all browser contexts. | -| [wsEndpoint()](./puppeteer.browser.wsendpoint.md) | | The browser websocket endpoint which can be used as an argument to [Puppeteer.connect()](./puppeteer.puppeteer.connect.md). | +| Method | Modifiers | Description | +| ---------------------------------------------------------------------------------------------- | --------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| [browserContexts()](./puppeteer.browser.browsercontexts.md) | | Returns an array of all open browser contexts. In a newly created browser, this will return a single instance of [BrowserContext](./puppeteer.browsercontext.md). | +| [close()](./puppeteer.browser.close.md) | | Closes the browser and all of its pages (if any were opened). The [Browser](./puppeteer.browser.md) object itself is considered to be disposed and cannot be used anymore. | +| [createIncognitoBrowserContext(options)](./puppeteer.browser.createincognitobrowsercontext.md) | | Creates a new incognito browser context. This won't share cookies/cache with other browser contexts. | +| [defaultBrowserContext()](./puppeteer.browser.defaultbrowsercontext.md) | | Returns the default browser context. The default browser context cannot be closed. | +| [disconnect()](./puppeteer.browser.disconnect.md) | | Disconnects Puppeteer from the browser, but leaves the browser process running. After calling disconnect, the [Browser](./puppeteer.browser.md) object is considered disposed and cannot be used anymore. | +| [isConnected()](./puppeteer.browser.isconnected.md) | | Indicates that the browser is connected. | +| [newPage()](./puppeteer.browser.newpage.md) | | Promise which resolves to a new [Page](./puppeteer.page.md) object. The Page is created in a default browser context. | +| [pages()](./puppeteer.browser.pages.md) | | An array of all open pages inside the Browser. | +| [process()](./puppeteer.browser.process.md) | | The spawned browser process. Returns null if the browser instance was created with [Puppeteer.connect()](./puppeteer.puppeteer.connect.md). | +| [target()](./puppeteer.browser.target.md) | | The target associated with the browser. | +| [targets()](./puppeteer.browser.targets.md) | | All active targets inside the Browser. In case of multiple browser contexts, returns an array with all the targets in all browser contexts. | +| [userAgent()](./puppeteer.browser.useragent.md) | | The browser's original user agent. Pages can override the browser user agent with [Page.setUserAgent()](./puppeteer.page.setuseragent.md). | +| [version()](./puppeteer.browser.version.md) | | A string representing the browser name and version. | +| [waitForTarget(predicate, options)](./puppeteer.browser.waitfortarget.md) | | Searches for a target in all browser contexts. | +| [wsEndpoint()](./puppeteer.browser.wsendpoint.md) | | The browser websocket endpoint which can be used as an argument to [Puppeteer.connect()](./puppeteer.puppeteer.connect.md). | diff --git a/docs/api/puppeteer.browser.version.md b/docs/api/puppeteer.browser.version.md index 205732a1bbe..a24cbc2fdfc 100644 --- a/docs/api/puppeteer.browser.version.md +++ b/docs/api/puppeteer.browser.version.md @@ -20,6 +20,6 @@ Promise<string> ## Remarks -For headless Chromium, this is similar to `HeadlessChrome/61.0.3153.0`. For non-headless, this is similar to `Chrome/61.0.3153.0`. +For headless browser, this is similar to `HeadlessChrome/61.0.3153.0`. For non-headless, this is similar to `Chrome/61.0.3153.0`. -The format of browser.version() might change with future releases of Chromium. +The format of browser.version() might change with future releases of browsers. diff --git a/docs/api/puppeteer.browseremittedevents.md b/docs/api/puppeteer.browseremittedevents.md index 8d567a6f686..e1c1eedf4e2 100644 --- a/docs/api/puppeteer.browseremittedevents.md +++ b/docs/api/puppeteer.browseremittedevents.md @@ -16,7 +16,7 @@ export declare const enum BrowserEmittedEvents | Member | Value | Description | | --------------- | ---------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| Disconnected | "disconnected" |

Emitted when Puppeteer gets disconnected from the Chromium instance. This might happen because of one of the following:

- Chromium is closed or crashed

- The [browser.disconnect](./puppeteer.browser.disconnect.md) method was called.

| +| Disconnected | "disconnected" |

Emitted when Puppeteer gets disconnected from the browser instance. This might happen because of one of the following:

- browser is closed or crashed

- The [browser.disconnect](./puppeteer.browser.disconnect.md) method was called.

| | TargetChanged | "targetchanged" | Emitted when the url of a target changes. Contains a [Target](./puppeteer.target.md) instance. | | TargetCreated | "targetcreated" |

Emitted when a target is created, for example when a new page is opened by [window.open](https://developer.mozilla.org/en-US/docs/Web/API/Window/open) or by [browser.newPage](./puppeteer.browser.newpage.md)

Contains a [Target](./puppeteer.target.md) instance.

| | TargetDestroyed | "targetdestroyed" | Emitted when a target is destroyed, for example when a page is closed. Contains a [Target](./puppeteer.target.md) instance. | diff --git a/docs/api/puppeteer.browserfetcher._constructor_.md b/docs/api/puppeteer.browserfetcher._constructor_.md deleted file mode 100644 index 600a5831e7e..00000000000 --- a/docs/api/puppeteer.browserfetcher._constructor_.md +++ /dev/null @@ -1,21 +0,0 @@ ---- -sidebar_label: BrowserFetcher.(constructor) ---- - -# BrowserFetcher.(constructor) - -Constructs a browser fetcher for the given options. - -#### Signature: - -```typescript -class BrowserFetcher { - constructor(options: BrowserFetcherOptions); -} -``` - -## Parameters - -| Parameter | Type | Description | -| --------- | ------------------------------------------------------------- | ----------- | -| options | [BrowserFetcherOptions](./puppeteer.browserfetcheroptions.md) | | diff --git a/docs/api/puppeteer.browserfetcher.candownload.md b/docs/api/puppeteer.browserfetcher.candownload.md deleted file mode 100644 index 33422c7dadd..00000000000 --- a/docs/api/puppeteer.browserfetcher.candownload.md +++ /dev/null @@ -1,31 +0,0 @@ ---- -sidebar_label: BrowserFetcher.canDownload ---- - -# BrowserFetcher.canDownload() method - -Initiates a HEAD request to check if the revision is available. - -#### Signature: - -```typescript -class BrowserFetcher { - canDownload(revision: string): Promise; -} -``` - -## Parameters - -| Parameter | Type | Description | -| --------- | ------ | --------------------------------------- | -| revision | string | The revision to check availability for. | - -**Returns:** - -Promise<boolean> - -A promise that resolves to `true` if the revision could be downloaded from the host. - -## Remarks - -This method is affected by the current `product`. diff --git a/docs/api/puppeteer.browserfetcher.download.md b/docs/api/puppeteer.browserfetcher.download.md deleted file mode 100644 index 740a4f202c7..00000000000 --- a/docs/api/puppeteer.browserfetcher.download.md +++ /dev/null @@ -1,35 +0,0 @@ ---- -sidebar_label: BrowserFetcher.download ---- - -# BrowserFetcher.download() method - -Initiates a GET request to download the revision from the host. - -#### Signature: - -```typescript -class BrowserFetcher { - download( - revision: string, - progressCallback?: (x: number, y: number) => void - ): Promise; -} -``` - -## Parameters - -| Parameter | Type | Description | -| ---------------- | --------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- | -| revision | string | The revision to download. | -| progressCallback | (x: number, y: number) => void | _(Optional)_ A function that will be called with two arguments: How many bytes have been downloaded and the total number of bytes of the download. | - -**Returns:** - -Promise<[BrowserFetcherRevisionInfo](./puppeteer.browserfetcherrevisioninfo.md) \| undefined> - -A promise with revision information when the revision is downloaded and extracted. - -## Remarks - -This method is affected by the current `product`. diff --git a/docs/api/puppeteer.browserfetcher.host.md b/docs/api/puppeteer.browserfetcher.host.md deleted file mode 100644 index 378b53abbd2..00000000000 --- a/docs/api/puppeteer.browserfetcher.host.md +++ /dev/null @@ -1,19 +0,0 @@ ---- -sidebar_label: BrowserFetcher.host ---- - -# BrowserFetcher.host() method - -The download host being used. - -#### Signature: - -```typescript -class BrowserFetcher { - host(): string; -} -``` - -**Returns:** - -string diff --git a/docs/api/puppeteer.browserfetcher.localrevisions.md b/docs/api/puppeteer.browserfetcher.localrevisions.md deleted file mode 100644 index a2a39087265..00000000000 --- a/docs/api/puppeteer.browserfetcher.localrevisions.md +++ /dev/null @@ -1,23 +0,0 @@ ---- -sidebar_label: BrowserFetcher.localRevisions ---- - -# BrowserFetcher.localRevisions() method - -#### Signature: - -```typescript -class BrowserFetcher { - localRevisions(): string[]; -} -``` - -**Returns:** - -string\[\] - -A list of all revision strings (for the current `product`) available locally on disk. - -## Remarks - -This method is affected by the current `product`. diff --git a/docs/api/puppeteer.browserfetcher.md b/docs/api/puppeteer.browserfetcher.md deleted file mode 100644 index 0b7a8caf0dc..00000000000 --- a/docs/api/puppeteer.browserfetcher.md +++ /dev/null @@ -1,48 +0,0 @@ ---- -sidebar_label: BrowserFetcher ---- - -# BrowserFetcher class - -BrowserFetcher can download and manage different versions of Chromium and Firefox. - -#### Signature: - -```typescript -export declare class BrowserFetcher -``` - -## Remarks - -BrowserFetcher is not designed to work concurrently with other instances of BrowserFetcher that share the same downloads directory. - -## Example - -An example of using BrowserFetcher to download a specific version of Chromium and running Puppeteer against it: - -```ts -const browserFetcher = new BrowserFetcher({path: 'path/to/download/folder'}); -const revisionInfo = await browserFetcher.download('533271'); -const browser = await puppeteer.launch({ - executablePath: revisionInfo.executablePath, -}); -``` - -## Constructors - -| Constructor | Modifiers | Description | -| --------------------------------------------------------------------- | --------- | --------------------------------------------------- | -| [(constructor)(options)](./puppeteer.browserfetcher._constructor_.md) | | Constructs a browser fetcher for the given options. | - -## Methods - -| Method | Modifiers | Description | -| ------------------------------------------------------------------------------ | --------- | ------------------------------------------------------------------------------------------------------------------------------------------ | -| [canDownload(revision)](./puppeteer.browserfetcher.candownload.md) | | Initiates a HEAD request to check if the revision is available. | -| [download(revision, progressCallback)](./puppeteer.browserfetcher.download.md) | | Initiates a GET request to download the revision from the host. | -| [host()](./puppeteer.browserfetcher.host.md) | | The download host being used. | -| [localRevisions()](./puppeteer.browserfetcher.localrevisions.md) | | | -| [platform()](./puppeteer.browserfetcher.platform.md) | | Returns the current Platform, which is one of mac, linux, win32 or win64. | -| [product()](./puppeteer.browserfetcher.product.md) | | Returns the current Product, which is one of chrome or firefox. | -| [remove(revision)](./puppeteer.browserfetcher.remove.md) | | | -| [revisionInfo(revision)](./puppeteer.browserfetcher.revisioninfo.md) | | | diff --git a/docs/api/puppeteer.browserfetcher.platform.md b/docs/api/puppeteer.browserfetcher.platform.md deleted file mode 100644 index 50ec11b3ba9..00000000000 --- a/docs/api/puppeteer.browserfetcher.platform.md +++ /dev/null @@ -1,19 +0,0 @@ ---- -sidebar_label: BrowserFetcher.platform ---- - -# BrowserFetcher.platform() method - -Returns the current `Platform`, which is one of `mac`, `linux`, `win32` or `win64`. - -#### Signature: - -```typescript -class BrowserFetcher { - platform(): Platform; -} -``` - -**Returns:** - -[Platform](./puppeteer.platform.md) diff --git a/docs/api/puppeteer.browserfetcher.product.md b/docs/api/puppeteer.browserfetcher.product.md deleted file mode 100644 index 826e696ef9b..00000000000 --- a/docs/api/puppeteer.browserfetcher.product.md +++ /dev/null @@ -1,19 +0,0 @@ ---- -sidebar_label: BrowserFetcher.product ---- - -# BrowserFetcher.product() method - -Returns the current `Product`, which is one of `chrome` or `firefox`. - -#### Signature: - -```typescript -class BrowserFetcher { - product(): Product; -} -``` - -**Returns:** - -[Product](./puppeteer.product.md) diff --git a/docs/api/puppeteer.browserfetcher.remove.md b/docs/api/puppeteer.browserfetcher.remove.md deleted file mode 100644 index 87237b75725..00000000000 --- a/docs/api/puppeteer.browserfetcher.remove.md +++ /dev/null @@ -1,29 +0,0 @@ ---- -sidebar_label: BrowserFetcher.remove ---- - -# BrowserFetcher.remove() method - -#### Signature: - -```typescript -class BrowserFetcher { - remove(revision: string): Promise; -} -``` - -## Parameters - -| Parameter | Type | Description | -| --------- | ------ | ---------------------------------------------------------- | -| revision | string | A revision to remove for the current product. | - -**Returns:** - -Promise<void> - -A promise that resolves when the revision has been removed or throws if the revision has not been downloaded. - -## Remarks - -This method is affected by the current `product`. diff --git a/docs/api/puppeteer.browserfetcher.revisioninfo.md b/docs/api/puppeteer.browserfetcher.revisioninfo.md deleted file mode 100644 index 0e3ef698693..00000000000 --- a/docs/api/puppeteer.browserfetcher.revisioninfo.md +++ /dev/null @@ -1,25 +0,0 @@ ---- -sidebar_label: BrowserFetcher.revisionInfo ---- - -# BrowserFetcher.revisionInfo() method - -#### Signature: - -```typescript -class BrowserFetcher { - revisionInfo(revision: string): BrowserFetcherRevisionInfo; -} -``` - -## Parameters - -| Parameter | Type | Description | -| --------- | ------ | ----------------------------- | -| revision | string | The revision to get info for. | - -**Returns:** - -[BrowserFetcherRevisionInfo](./puppeteer.browserfetcherrevisioninfo.md) - -The revision info for the given revision. diff --git a/docs/api/puppeteer.browserfetcheroptions.md b/docs/api/puppeteer.browserfetcheroptions.md deleted file mode 100644 index 6d1c93fcefe..00000000000 --- a/docs/api/puppeteer.browserfetcheroptions.md +++ /dev/null @@ -1,21 +0,0 @@ ---- -sidebar_label: BrowserFetcherOptions ---- - -# BrowserFetcherOptions interface - -#### Signature: - -```typescript -export interface BrowserFetcherOptions -``` - -## Properties - -| Property | Modifiers | Type | Description | Default | -| ----------------- | --------------------- | ----------------------------------- | ------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------- | -| host | optional | string | Determines the host that will be used for downloading. |

Either

- https://storage.googleapis.com or - https://archive.mozilla.org/pub/firefox/nightly/latest-mozilla-central

| -| path | | string | Determines the path to download browsers to. | | -| platform | optional | [Platform](./puppeteer.platform.md) | Determines which platform the browser will be suited for. | **Auto-detected.** | -| product | optional | 'chrome' \| 'firefox' | Determines which product the [BrowserFetcher](./puppeteer.browserfetcher.md) is for. | chrome | -| useMacOSARMBinary | optional | boolean | Enables the use of the Chromium binary for macOS ARM. | | diff --git a/docs/api/puppeteer.browserfetcherrevisioninfo.md b/docs/api/puppeteer.browserfetcherrevisioninfo.md deleted file mode 100644 index 36d5c1756af..00000000000 --- a/docs/api/puppeteer.browserfetcherrevisioninfo.md +++ /dev/null @@ -1,22 +0,0 @@ ---- -sidebar_label: BrowserFetcherRevisionInfo ---- - -# BrowserFetcherRevisionInfo interface - -#### Signature: - -```typescript -export interface BrowserFetcherRevisionInfo -``` - -## Properties - -| Property | Modifiers | Type | Description | Default | -| -------------- | --------- | ------- | ----------- | ------- | -| executablePath | | string | | | -| folderPath | | string | | | -| local | | boolean | | | -| product | | string | | | -| revision | | string | | | -| url | | string | | | diff --git a/docs/api/puppeteer.configuration.md b/docs/api/puppeteer.configuration.md index 5f64f889847..47f13912f2b 100644 --- a/docs/api/puppeteer.configuration.md +++ b/docs/api/puppeteer.configuration.md @@ -21,7 +21,7 @@ export interface Configuration | browserRevision | optional | string |

Specifies a certain version of the browser you'd like Puppeteer to use.

Can be overridden by PUPPETEER_BROWSER_REVISION.

See [puppeteer.launch](./puppeteer.puppeteernode.launch.md) on how executable path is inferred.

| A compatible-revision of the browser. | | cacheDirectory | optional | string |

Defines the directory to be used by Puppeteer for caching.

Can be overridden by PUPPETEER_CACHE_DIR.

| path.join(os.homedir(), '.cache', 'puppeteer') | | defaultProduct | optional | [Product](./puppeteer.product.md) |

Specifies which browser you'd like Puppeteer to use.

Can be overridden by PUPPETEER_PRODUCT.

| chrome | -| downloadHost | optional | string |

Specifies the URL prefix that is used to download Chromium.

Can be overridden by PUPPETEER_DOWNLOAD_HOST.

| Either https://storage.googleapis.com or https://archive.mozilla.org/pub/firefox/nightly/latest-mozilla-central, depending on the product. | +| downloadHost | optional | string |

Specifies the URL prefix that is used to download the browser.

Can be overridden by PUPPETEER_DOWNLOAD_HOST.

| Either https://storage.googleapis.com or https://archive.mozilla.org/pub/firefox/nightly/latest-mozilla-central, depending on the product. | | downloadPath | optional | string |

Specifies the path for the downloads folder.

Can be overridden by PUPPETEER_DOWNLOAD_PATH.

| <cache>/<product> where <cache> is Puppeteer's cache directory and <product> is the name of the browser. | | executablePath | optional | string |

Specifies an executable path to be used in [puppeteer.launch](./puppeteer.puppeteernode.launch.md).

Can be overridden by PUPPETEER_EXECUTABLE_PATH.

| **Auto-computed.** | | experiments | optional | [ExperimentsConfiguration](./puppeteer.experimentsconfiguration.md) | Defines experimental options for Puppeteer. | | diff --git a/docs/api/puppeteer.createbrowserfetcher.md b/docs/api/puppeteer.createbrowserfetcher.md deleted file mode 100644 index 6521b6a0146..00000000000 --- a/docs/api/puppeteer.createbrowserfetcher.md +++ /dev/null @@ -1,17 +0,0 @@ ---- -sidebar_label: createBrowserFetcher ---- - -# createBrowserFetcher variable - -#### Signature: - -```typescript -createBrowserFetcher: ( - options?: - | Partial< - import('puppeteer-core/internal/puppeteer-core.js').BrowserFetcherOptions - > - | undefined -) => import('puppeteer-core/internal/puppeteer-core.js').BrowserFetcher; -``` diff --git a/docs/api/puppeteer.experimentsconfiguration.md b/docs/api/puppeteer.experimentsconfiguration.md index 035ee31db1d..9c7ae85053c 100644 --- a/docs/api/puppeteer.experimentsconfiguration.md +++ b/docs/api/puppeteer.experimentsconfiguration.md @@ -2,7 +2,7 @@ sidebar_label: ExperimentsConfiguration --- -# ExperimentsConfiguration interface +# ExperimentsConfiguration type Defines experiment options for Puppeteer. @@ -11,11 +11,5 @@ See individual properties for more information. #### Signature: ```typescript -export interface ExperimentsConfiguration +export type ExperimentsConfiguration = Record; ``` - -## Properties - -| Property | Modifiers | Type | Description | Default | -| --------------------- | --------------------- | ------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------ | -| macArmChromiumEnabled | optional | boolean |

Require Puppeteer to download Chromium for Apple M1.

On Apple M1 devices Puppeteer by default downloads the version for Intel's processor which runs via Rosetta. It works without any problems, however, with this option, you should get more efficient resource usage (CPU and RAM) that could lead to a faster execution time.

Can be overridden by PUPPETEER_EXPERIMENTAL_CHROMIUM_MAC_ARM.

| false | diff --git a/docs/api/puppeteer.page.md b/docs/api/puppeteer.page.md index 85b86220414..d84f8090bd0 100644 --- a/docs/api/puppeteer.page.md +++ b/docs/api/puppeteer.page.md @@ -4,7 +4,7 @@ sidebar_label: Page # Page class -Page provides methods to interact with a single tab or [extension background page](https://developer.chrome.com/extensions/background_pages) in Chromium. +Page provides methods to interact with a single tab or [extension background page](https://developer.chrome.com/extensions/background_pages) in the browser. :::note @@ -63,14 +63,14 @@ page.off('request', logRequest); ## Properties -| Property | Modifiers | Type | Description | -| ------------- | --------------------- | --------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| accessibility | readonly | [Accessibility](./puppeteer.accessibility.md) | The Accessibility class provides methods for inspecting Chromium's accessibility tree. The accessibility tree is used by assistive technology such as [screen readers](https://en.wikipedia.org/wiki/Screen_reader) or [switches](https://en.wikipedia.org/wiki/Switch_access). | -| coverage | readonly | [Coverage](./puppeteer.coverage.md) | The Coverage class provides methods to gather information about parts of JavaScript and CSS that were used by the page. | -| keyboard | readonly | [Keyboard](./puppeteer.keyboard.md) | Keyboard provides an api for managing a virtual keyboard. The high level api is [Keyboard.type()](./puppeteer.keyboard.type.md), which takes raw characters and generates proper keydown, keypress/input, and keyup events on your page. | -| mouse | readonly | [Mouse](./puppeteer.mouse.md) | The Mouse class operates in main-frame CSS pixels relative to the top-left corner of the viewport. | -| touchscreen | readonly | [Touchscreen](./puppeteer.touchscreen.md) | The Touchscreen class exposes touchscreen events. | -| tracing | readonly | [Tracing](./puppeteer.tracing.md) | The Tracing class exposes the tracing audit interface. | +| Property | Modifiers | Type | Description | +| ------------- | --------------------- | --------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| accessibility | readonly | [Accessibility](./puppeteer.accessibility.md) | The Accessibility class provides methods for inspecting the browser's accessibility tree. The accessibility tree is used by assistive technology such as [screen readers](https://en.wikipedia.org/wiki/Screen_reader) or [switches](https://en.wikipedia.org/wiki/Switch_access). | +| coverage | readonly | [Coverage](./puppeteer.coverage.md) | The Coverage class provides methods to gather information about parts of JavaScript and CSS that were used by the page. | +| keyboard | readonly | [Keyboard](./puppeteer.keyboard.md) | Keyboard provides an api for managing a virtual keyboard. The high level api is [Keyboard.type()](./puppeteer.keyboard.type.md), which takes raw characters and generates proper keydown, keypress/input, and keyup events on your page. | +| mouse | readonly | [Mouse](./puppeteer.mouse.md) | The Mouse class operates in main-frame CSS pixels relative to the top-left corner of the viewport. | +| touchscreen | readonly | [Touchscreen](./puppeteer.touchscreen.md) | The Touchscreen class exposes touchscreen events. | +| tracing | readonly | [Tracing](./puppeteer.tracing.md) | The Tracing class exposes the tracing audit interface. | ## Methods diff --git a/docs/api/puppeteer.page.waitforfilechooser.md b/docs/api/puppeteer.page.waitforfilechooser.md index 57333a33874..ba2ee47a3d1 100644 --- a/docs/api/puppeteer.page.waitforfilechooser.md +++ b/docs/api/puppeteer.page.waitforfilechooser.md @@ -32,7 +32,7 @@ Promise<[FileChooser](./puppeteer.filechooser.md)> ## Remarks -In non-headless Chromium, this method results in the native file picker dialog `not showing up` for the user. +In the "headful" browser, this method results in the native file picker dialog `not showing up` for the user. ## Example diff --git a/docs/api/puppeteer.platform.md b/docs/api/puppeteer.platform.md deleted file mode 100644 index 9d61793f2fa..00000000000 --- a/docs/api/puppeteer.platform.md +++ /dev/null @@ -1,13 +0,0 @@ ---- -sidebar_label: Platform ---- - -# Platform type - -Supported platforms. - -#### Signature: - -```typescript -export type Platform = 'linux' | 'mac' | 'mac_arm' | 'win32' | 'win64'; -``` diff --git a/docs/api/puppeteer.puppeteernode.createbrowserfetcher.md b/docs/api/puppeteer.puppeteernode.createbrowserfetcher.md deleted file mode 100644 index 2a42acda8e1..00000000000 --- a/docs/api/puppeteer.puppeteernode.createbrowserfetcher.md +++ /dev/null @@ -1,31 +0,0 @@ ---- -sidebar_label: PuppeteerNode.createBrowserFetcher ---- - -# PuppeteerNode.createBrowserFetcher() method - -#### Signature: - -```typescript -class PuppeteerNode { - createBrowserFetcher( - options?: Partial - ): BrowserFetcher; -} -``` - -## Parameters - -| Parameter | Type | Description | -| --------- | ---------------------------------------------------------------------------- | --------------------------------------------------------------------------------------- | -| options | Partial<[BrowserFetcherOptions](./puppeteer.browserfetcheroptions.md)> | _(Optional)_ Set of configurable options to specify the settings of the BrowserFetcher. | - -**Returns:** - -[BrowserFetcher](./puppeteer.browserfetcher.md) - -A new BrowserFetcher instance. - -## Remarks - -If you are using `puppeteer-core`, do not use this method. Just construct [BrowserFetcher](./puppeteer.browserfetcher.md) manually. diff --git a/docs/api/puppeteer.puppeteernode.launch.md b/docs/api/puppeteer.puppeteernode.launch.md index 1762eb22145..4b1db660e55 100644 --- a/docs/api/puppeteer.puppeteernode.launch.md +++ b/docs/api/puppeteer.puppeteernode.launch.md @@ -28,7 +28,7 @@ Promise<[Browser](./puppeteer.browser.md)> ## Remarks -Puppeteer can also be used to control the Chrome browser, but it works best with the version of Chromium downloaded by default by Puppeteer. There is no guarantee it will work with any other version. If Google Chrome (rather than Chromium) is preferred, a [Chrome Canary](https://www.google.com/chrome/browser/canary.html) or [Dev Channel](https://www.chromium.org/getting-involved/dev-channel) build is suggested. See [this article](https://www.howtogeek.com/202825/what%E2%80%99s-the-difference-between-chromium-and-chrome/) for a description of the differences between Chromium and Chrome. [This article](https://chromium.googlesource.com/chromium/src/+/lkgr/docs/chromium_browser_vs_google_chrome.md) describes some differences for Linux users. +Puppeteer can also be used to control the Chrome browser, but it works best with the version of Chrome for Testing downloaded by default. There is no guarantee it will work with any other version. If Google Chrome (rather than Chrome for Testing) is preferred, a [Chrome Canary](https://www.google.com/chrome/browser/canary.html) or [Dev Channel](https://www.chromium.org/getting-involved/dev-channel) build is suggested. See [this article](https://www.howtogeek.com/202825/what%E2%80%99s-the-difference-between-chromium-and-chrome/) for a description of the differences between Chromium and Chrome. [This article](https://chromium.googlesource.com/chromium/src/+/lkgr/docs/chromium_browser_vs_google_chrome.md) describes some differences for Linux users. See [this doc](https://goo.gle/chrome-for-testing) for the description of Chrome for Testing. ## Example diff --git a/docs/api/puppeteer.puppeteernode.md b/docs/api/puppeteer.puppeteernode.md index ae6c94ed5f0..1a022978917 100644 --- a/docs/api/puppeteer.puppeteernode.md +++ b/docs/api/puppeteer.puppeteernode.md @@ -52,10 +52,9 @@ Once you have created a `page` you have access to a large API to interact with t ## Methods -| Method | Modifiers | Description | -| ---------------------------------------------------------------------------------- | --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -| [connect(options)](./puppeteer.puppeteernode.connect.md) | | This method attaches Puppeteer to an existing browser instance. | -| [createBrowserFetcher(options)](./puppeteer.puppeteernode.createbrowserfetcher.md) | | | -| [defaultArgs(options)](./puppeteer.puppeteernode.defaultargs.md) | | | -| [executablePath(channel)](./puppeteer.puppeteernode.executablepath.md) | | The default executable path. | -| [launch(options)](./puppeteer.puppeteernode.launch.md) | |

Launches a browser instance with given arguments and options when specified.

When using with puppeteer-core, [options.executablePath](./puppeteer.launchoptions.md) or [options.channel](./puppeteer.launchoptions.md) must be provided.

| +| Method | Modifiers | Description | +| ---------------------------------------------------------------------- | --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| [connect(options)](./puppeteer.puppeteernode.connect.md) | | This method attaches Puppeteer to an existing browser instance. | +| [defaultArgs(options)](./puppeteer.puppeteernode.defaultargs.md) | | | +| [executablePath(channel)](./puppeteer.puppeteernode.executablepath.md) | | The default executable path. | +| [launch(options)](./puppeteer.puppeteernode.launch.md) | |

Launches a browser instance with given arguments and options when specified.

When using with puppeteer-core, [options.executablePath](./puppeteer.launchoptions.md) or [options.channel](./puppeteer.launchoptions.md) must be provided.

| diff --git a/docs/contributing.md b/docs/contributing.md index cd61905592f..777a5347a97 100644 --- a/docs/contributing.md +++ b/docs/contributing.md @@ -48,23 +48,6 @@ again. npm test ``` -### macOS ARM and custom executables. - -- To run experimental Chromium macOS ARM tests, firstly ensure you have correct - Chromium version installed locally (you only need to do this once, not on - every test run) and then you can run the tests: - - ```bash - PUPPETEER_EXPERIMENTAL_CHROMIUM_MAC_ARM=1 npm install - PUPPETEER_EXPERIMENTAL_CHROMIUM_MAC_ARM=1 npm run test - ``` - -- To run tests with custom browser executable: - - ```bash - BINARY= npm run test:chrome # Or npm run test:firefox - ``` - ## Building a single package To build a single package, you can run: @@ -280,18 +263,15 @@ npm run build --workspace @puppeteer-test/test # For Project Maintainers -## Rolling new Chromium version +## Rolling new Chrome version -The following steps are needed to update the Chromium version. +The following steps are needed to update the Chrome version. -1. Find a suitable Chromium revision. Not all revisions have builds for all - platforms, so we need to find one that does. The easiest way is to run - `tools/check_availability.js -rd` to find the latest suitable `dev` Chromium - revision (see `tools/check_availability.js -help` for more options). -2. Update `packages/puppeteer-core/src/revisions.ts` with the found revision +1. Find a suitable Chrome revision via https://mathiasbynens.github.io/chrome-for-testing/ or https://chromiumdash.appspot.com/. +2. Update `packages/puppeteer-core/src/revisions.ts` with the found version number. -3. Update `versions.js` with the new Chromium-to-Puppeteer version mapping and - update `lastMaintainedChromiumVersion` with the latest stable Chrome version. +3. Update `versions.js` with the new Chrome-to-Puppeteer version mapping and + update `lastMaintainedChromeVersion` with the latest stable Chrome version. You can find the corresponding version by going to [omahaproxy.appspot.com](https://omahaproxy.appspot.com/) then searching in `Find Releases` for `r`. 4. Run `npm run check`. If it fails, update @@ -304,26 +284,13 @@ The following steps are needed to update the Chromium version. change) or work around the changes in Puppeteer (if it’s not desirable to change Puppeteer’s observable behavior). 7. Commit and push your changes and open a pull request. The commit message must - contain the version in `Chromium (r)` format to ensure + contain the version in `Chrome (r)` format to ensure that [pptr.dev](https://pptr.dev/) can parse it correctly, e.g. - `'feat(chromium): roll to Chromium 90.0.4427.0 (r856583)'`. + `'feat(chrome): roll to Chrome 90.0.4427.0 (r856583)'`. ### Bisecting upstream changes -Sometimes, performing a Chromium roll causes tests to fail. To figure out the -cause, you need to bisect Chromium revisions to figure out the earliest possible -revision that changed the behavior. The `bisect` script can be helpful here. -Given a pattern for one or more unit tests, it will automatically bisect the -current range: - -```bash -npm run bisect -- --good 686378 --bad 706915 script.js -npm run bisect -- --unit-test Response.fromCache -``` - -By default, it will use the Chromium revision in -`packages/puppeteer-core/src/revisions.ts` from the `main` branch and from the -working tree to determine the range to bisect. +For bisecting Chrome/Chromium changes use https://www.chromium.org/developers/bisect-builds-py/. ## Releasing to npm diff --git a/docs/faq.md b/docs/faq.md index d22128956a2..a23efe9849e 100644 --- a/docs/faq.md +++ b/docs/faq.md @@ -97,19 +97,10 @@ taking place in the Chromium repository. Here’s a typical story: - Once the upstream fix is landed, we roll updated Chromium into Puppeteer: https://github.com/puppeteer/puppeteer/pull/2769 -## Q: Which Chromium version does Puppeteer use? +## Q: Which Chrome version does Puppeteer use? -Find the version using one of the following ways: - -- Look for the `chromium` entry in - [revisions.ts](https://github.com/puppeteer/puppeteer/blob/main/packages/puppeteer-core/src/revisions.ts). - To find the corresponding Chromium commit and version number, search for the - revision prefixed by an `r` in [OmahaProxy](https://omahaproxy.appspot.com/)'s - "Find Releases" section. -- Look for the `versionsPerRelease` map in - [versions.js](https://github.com/puppeteer/puppeteer/blob/main/versions.js) - which contains mapping between Chromium and the smallest Puppeteer version - that supports it. +Look for the `chrome` entry in +[revisions.ts](https://github.com/puppeteer/puppeteer/blob/main/packages/puppeteer-core/src/revisions.ts). ## Q: Which Firefox version does Puppeteer use? @@ -175,7 +166,7 @@ that incorporate audio and video. (For example, [video playback/screenshots is likely to fail](https://github.com/puppeteer/puppeteer/issues/291).) There are two reasons for this: -- Puppeteer is bundled with Chromium — not Chrome — and so by default, it +- Puppeteer is bundled with [Chrome for Testing](https://goo.gle/chrome-for-testing) — not the regular Chrome — and so by default, it inherits all of [Chromium's media-related limitations](https://www.chromium.org/audio-video). This means that Puppeteer does not support licensed formats such as AAC or @@ -195,30 +186,6 @@ We have a [troubleshooting](https://pptr.dev/troubleshooting) guide for various operating systems that lists the required dependencies. -#### Q: Chromium gets downloaded on every `npm ci` run. How can I cache the download? - -The default download path is `node_modules/puppeteer/.local-chromium`. However, -you can change that path with the `PUPPETEER_DOWNLOAD_PATH` environment -variable. - -Puppeteer uses that variable to resolve the Chromium executable location during -launch, so you don’t need to specify `PUPPETEER_EXECUTABLE_PATH` as well. - -For example, if you wish to keep the Chromium download in `~/.npm/chromium`: - -```bash -export PUPPETEER_DOWNLOAD_PATH=~/.npm/chromium -npm ci - -# by default the Chromium executable path is inferred -# from the download path -npm test - -# a new run of npm ci will check for the existence of -# Chromium in ~/.npm/chromium -npm ci -``` - #### Q: I have more questions! Where do I ask? There are many ways to get help on Puppeteer: diff --git a/docs/guides/configuration.mdx b/docs/guides/configuration.mdx index c6e11edda6b..4a47d3b7a0d 100644 --- a/docs/guides/configuration.mdx +++ b/docs/guides/configuration.mdx @@ -78,49 +78,6 @@ about the ambient environment is needed (in this case, `__dirname`). ::: -#### Enabling experiments - -By default, experiments are turned off, but they can be individually turned on -using the [`experiments`](../api/puppeteer.configuration) key. - -For example, if you want to enable ARM-native macOS chromium, you can use - - - - -```js title=".puppeteerrc.cjs" -/** - * @type {import("puppeteer").Configuration} - */ -module.exports = { - experiments: { - macArmChromiumEnabled: true, - }, -}; -``` - - - - -```json title=".puppeteerrc.json" -{ - "experiments": { - "macArmChromiumEnabled": true - } -} -``` - - - - -```yaml title=".puppeteerrc.yaml" -experiments: - macArmChromiumEnabled: true -``` - - - - ## Environment variables Along with configuration files, Puppeteer looks for certain diff --git a/docs/guides/docker.md b/docs/guides/docker.md index 5f84c5211ba..2391aacd546 100644 --- a/docs/guides/docker.md +++ b/docs/guides/docker.md @@ -1,6 +1,6 @@ # Docker -Puppeteer offers a Docker image that includes Chromium along with the required +Puppeteer offers a Docker image that includes [Chrome for Testing](https://goo.gle/chrome-for-testing) along with the required dependencies and a pre-installed Puppeteer version. The image is available via the [GitHub Container Registry](https://github.com/puppeteer/puppeteer/pkgs/container/puppeteer). diff --git a/docs/index.md b/docs/index.md index 424c9d9eb00..a7df543c828 100644 --- a/docs/index.md +++ b/docs/index.md @@ -12,7 +12,7 @@ > [DevTools Protocol](https://chromedevtools.github.io/devtools-protocol/). > Puppeteer runs in > [headless](https://developer.chrome.com/articles/new-headless/) -> mode by default, but can be configured to run in full (non-headless) +> mode by default, but can be configured to run in full ("headful") > Chrome/Chromium. #### What can I do? @@ -46,7 +46,7 @@ pnpm i puppeteer ``` When you install Puppeteer, it automatically downloads a recent version of -Chromium (~170MB macOS, ~282MB Linux, ~280MB Windows) that is [guaranteed to +[Chrome for Testing](https://goo.gle/chrome-for-testing) (~170MB macOS, ~282MB Linux, ~280MB Windows) that is [guaranteed to work](https://pptr.dev/faq#q-why-doesnt-puppeteer-vxxx-work-with-chromium-vyyy) with Puppeteer. The browser is downloaded to the `$HOME/.cache/puppeteer` folder by default (starting with Puppeteer v19.0.0). @@ -94,14 +94,14 @@ Every release since v1.7.0 we publish two packages: - [`puppeteer-core`](https://www.npmjs.com/package/puppeteer-core) `puppeteer` is a _product_ for browser automation. When installed, it downloads -a version of Chromium, which it then drives using `puppeteer-core`. Being an +a version of Chrome, which it then drives using `puppeteer-core`. Being an end-user product, `puppeteer` automates several workflows using reasonable defaults [that can be customized](https://pptr.dev/guides/configuration). `puppeteer-core` is a _library_ to help drive anything that supports DevTools protocol. Being a library, `puppeteer-core` is fully driven through its programmatic interface implying no defaults are assumed and `puppeteer-core` -will not download Chromium when installed. +will not download Chrome when installed. You should use `puppeteer-core` if you are [connecting to a remote browser](https://pptr.dev/api/puppeteer.puppeteer.connect) @@ -176,7 +176,7 @@ import puppeteer from 'puppeteer'; **1. Uses Headless mode** -By default Puppeteer launches Chromium in +By default Puppeteer launches Chrome in [old Headless mode](https://developer.chrome.com/articles/new-headless/). ```ts @@ -193,17 +193,17 @@ We recommend you try it out before the switch: const browser = await puppeteer.launch({headless: 'new'}); ``` -To launch a full version of Chromium, set the -[`headless`](https://pptr.dev/api/puppeteer.browserlaunchargumentoptions) to `true` +To launch a "headful" version of Chrome, set the +[`headless`](https://pptr.dev/api/puppeteer.browserlaunchargumentoptions) to `false` option when launching a browser: ```ts const browser = await puppeteer.launch({headless: false}); ``` -**2. Runs a bundled version of Chromium** +**2. Runs a bundled version of Chrome** -By default, Puppeteer downloads and uses a specific version of Chromium so its +By default, Puppeteer downloads and uses a specific version of Chrome so its API is guaranteed to work out of the box. To use Puppeteer with a different version of Chrome or Chromium, pass in the executable's path when creating a `Browser` instance: diff --git a/package.json b/package.json index 5b75cf01792..508847bcba5 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,6 @@ "url": "https://github.com/puppeteer/puppeteer" }, "scripts": { - "bisect": "tsx tools/bisect.ts", "build": "wireit", "build:docs": "wireit", "check:pinned-deps": "tsx tools/ensure-pinned-deps", diff --git a/packages/browsers/src/Cache.ts b/packages/browsers/src/Cache.ts index 0cb31b95d0f..142bceb08ec 100644 --- a/packages/browsers/src/Cache.ts +++ b/packages/browsers/src/Cache.ts @@ -51,12 +51,7 @@ export class Cache { } browserRoot(browser: Browser): string { - // Chromium is a special case for backward compatibility: we install it in - // the Chrome folder so that Puppeteer can find it. - return path.join( - this.#rootDir, - browser === Browser.CHROMIUM ? Browser.CHROME : browser - ); + return path.join(this.#rootDir, browser); } installationDir( diff --git a/packages/browsers/test/src/chromium/launch.spec.ts b/packages/browsers/test/src/chromium/launch.spec.ts index 2d5d704887c..7fade9e52de 100644 --- a/packages/browsers/test/src/chromium/launch.spec.ts +++ b/packages/browsers/test/src/chromium/launch.spec.ts @@ -39,7 +39,7 @@ describe('Chromium', () => { buildId: '123', cacheDir: 'cache', }), - path.join('cache', 'chrome', 'linux-123', 'chrome-linux', 'chrome') + path.join('cache', 'chromium', 'linux-123', 'chrome-linux', 'chrome') ); }); diff --git a/packages/puppeteer-core/src/api/Browser.ts b/packages/puppeteer-core/src/api/Browser.ts index ccf364d9e97..5a08f6ec171 100644 --- a/packages/puppeteer-core/src/api/Browser.ts +++ b/packages/puppeteer-core/src/api/Browser.ts @@ -131,10 +131,10 @@ export interface WaitForTargetOptions { */ export const enum BrowserEmittedEvents { /** - * Emitted when Puppeteer gets disconnected from the Chromium instance. This + * Emitted when Puppeteer gets disconnected from the browser instance. This * might happen because of one of the following: * - * - Chromium is closed or crashed + * - browser is closed or crashed * * - The {@link Browser.disconnect | browser.disconnect } method was called. */ @@ -173,7 +173,7 @@ export const enum BrowserEmittedEvents { } /** - * A Browser is created when Puppeteer connects to a Chromium instance, either through + * A Browser is created when Puppeteer connects to a browser instance, either through * {@link PuppeteerNode.launch} or {@link Puppeteer.connect}. * * @remarks @@ -203,14 +203,14 @@ export const enum BrowserEmittedEvents { * * (async () => { * const browser = await puppeteer.launch(); - * // Store the endpoint to be able to reconnect to Chromium + * // Store the endpoint to be able to reconnect to the browser. * const browserWSEndpoint = browser.wsEndpoint(); - * // Disconnect puppeteer from Chromium + * // Disconnect puppeteer from the browser. * browser.disconnect(); * * // Use the endpoint to reestablish a connection * const browser2 = await puppeteer.connect({browserWSEndpoint}); - * // Close Chromium + * // Close the browser. * await browser2.close(); * })(); * ``` @@ -404,10 +404,10 @@ export class Browser extends EventEmitter { * * @remarks * - * For headless Chromium, this is similar to `HeadlessChrome/61.0.3153.0`. For + * For headless browser, this is similar to `HeadlessChrome/61.0.3153.0`. For * non-headless, this is similar to `Chrome/61.0.3153.0`. * - * The format of browser.version() might change with future releases of Chromium. + * The format of browser.version() might change with future releases of browsers. */ version(): Promise { throw new Error('Not implemented'); @@ -422,15 +422,16 @@ export class Browser extends EventEmitter { } /** - * Closes Chromium and all of its pages (if any were opened). The {@link Browser} object - * itself is considered to be disposed and cannot be used anymore. + * Closes the browser and all of its pages (if any were opened). The + * {@link Browser} object itself is considered to be disposed and cannot be + * used anymore. */ close(): Promise { throw new Error('Not implemented'); } /** - * Disconnects Puppeteer from the browser, but leaves the Chromium process running. + * Disconnects Puppeteer from the browser, but leaves the browser process running. * After calling `disconnect`, the {@link Browser} object is considered disposed and * cannot be used anymore. */ diff --git a/packages/puppeteer-core/src/api/Page.ts b/packages/puppeteer-core/src/api/Page.ts index 2bfa7fe5a6b..10fcbfccdaa 100644 --- a/packages/puppeteer-core/src/api/Page.ts +++ b/packages/puppeteer-core/src/api/Page.ts @@ -388,7 +388,7 @@ export interface PageEventObject { /** * Page provides methods to interact with a single tab or * {@link https://developer.chrome.com/extensions/background_pages | extension background page} - * in Chromium. + * in the browser. * * :::note * @@ -521,7 +521,7 @@ export class Page extends EventEmitter { * ::: * * @remarks - * In non-headless Chromium, this method results in the native file picker + * In the "headful" browser, this method results in the native file picker * dialog `not showing up` for the user. * * @example diff --git a/packages/puppeteer-core/src/common/Accessibility.ts b/packages/puppeteer-core/src/common/Accessibility.ts index 53fbb9767d1..1429ecf6072 100644 --- a/packages/puppeteer-core/src/common/Accessibility.ts +++ b/packages/puppeteer-core/src/common/Accessibility.ts @@ -110,7 +110,7 @@ export interface SnapshotOptions { } /** - * The Accessibility class provides methods for inspecting Chromium's + * The Accessibility class provides methods for inspecting the browser's * accessibility tree. The accessibility tree is used by assistive technology * such as {@link https://en.wikipedia.org/wiki/Screen_reader | screen readers} or * {@link https://en.wikipedia.org/wiki/Switch_access | switches}. @@ -147,7 +147,7 @@ export class Accessibility { * * @remarks * - * **NOTE** The Chromium accessibility tree contains nodes that go unused on + * **NOTE** The Chrome accessibility tree contains nodes that go unused on * most platforms and by most screen readers. Puppeteer will discard them as * well for an easier to process tree, unless `interestingOnly` is set to * `false`. diff --git a/packages/puppeteer-core/src/common/Browser.ts b/packages/puppeteer-core/src/common/Browser.ts index 8cb2de51a8d..6a2b46f2e20 100644 --- a/packages/puppeteer-core/src/common/Browser.ts +++ b/packages/puppeteer-core/src/common/Browser.ts @@ -522,16 +522,6 @@ export class CDPBrowser extends BrowserBase { }, []); } - /** - * A string representing the browser name and version. - * - * @remarks - * - * For headless Chromium, this is similar to `HeadlessChrome/61.0.3153.0`. For - * non-headless, this is similar to `Chrome/61.0.3153.0`. - * - * The format of browser.version() might change with future releases of Chromium. - */ override async version(): Promise { const version = await this.#getVersion(); return version.product; @@ -546,21 +536,11 @@ export class CDPBrowser extends BrowserBase { return version.userAgent; } - /** - * Closes Chromium and all of its pages (if any were opened). The - * {@link CDPBrowser} object itself is considered to be disposed and cannot be - * used anymore. - */ override async close(): Promise { await this.#closeCallback.call(null); this.disconnect(); } - /** - * Disconnects Puppeteer from the browser, but leaves the Chromium process running. - * After calling `disconnect`, the {@link CDPBrowser} object is considered disposed and - * cannot be used anymore. - */ override disconnect(): void { this.#targetManager.dispose(); this.#connection.dispose(); diff --git a/packages/puppeteer-core/src/common/Configuration.ts b/packages/puppeteer-core/src/common/Configuration.ts index e17c1503ade..6db94c34528 100644 --- a/packages/puppeteer-core/src/common/Configuration.ts +++ b/packages/puppeteer-core/src/common/Configuration.ts @@ -23,21 +23,7 @@ import {Product} from './Product.js'; * * @public */ -export interface ExperimentsConfiguration { - /** - * Require Puppeteer to download Chromium for Apple M1. - * - * On Apple M1 devices Puppeteer by default downloads the version for - * Intel's processor which runs via Rosetta. It works without any problems, - * however, with this option, you should get more efficient resource usage - * (CPU and RAM) that could lead to a faster execution time. - * - * Can be overridden by `PUPPETEER_EXPERIMENTAL_CHROMIUM_MAC_ARM`. - * - * @defaultValue `false` - */ - macArmChromiumEnabled?: boolean; -} +export type ExperimentsConfiguration = Record; /** * Defines options to configure Puppeteer's behavior during installation and @@ -68,7 +54,7 @@ export interface Configuration { */ cacheDirectory?: string; /** - * Specifies the URL prefix that is used to download Chromium. + * Specifies the URL prefix that is used to download the browser. * * Can be overridden by `PUPPETEER_DOWNLOAD_HOST`. * diff --git a/packages/puppeteer-core/src/common/util.ts b/packages/puppeteer-core/src/common/util.ts index 9ec69b2f5f4..d9b66934dec 100644 --- a/packages/puppeteer-core/src/common/util.ts +++ b/packages/puppeteer-core/src/common/util.ts @@ -394,11 +394,14 @@ export async function getReadableAsBuffer( if (path) { const fs = await importFSPromises(); const fileHandle = await fs.open(path, 'w+'); - for await (const chunk of readable) { - buffers.push(chunk); - await fileHandle.writeFile(chunk); + try { + for await (const chunk of readable) { + buffers.push(chunk); + await fileHandle.writeFile(chunk); + } + } finally { + await fileHandle.close(); } - await fileHandle.close(); } else { for await (const chunk of readable) { buffers.push(chunk); @@ -433,12 +436,20 @@ export async function getReadableFromProtocolStream( return; } - const response = await client.send('IO.read', {handle, size}); - this.push(response.data, response.base64Encoded ? 'base64' : undefined); - if (response.eof) { - eof = true; - await client.send('IO.close', {handle}); - this.push(null); + try { + const response = await client.send('IO.read', {handle, size}); + this.push(response.data, response.base64Encoded ? 'base64' : undefined); + if (response.eof) { + eof = true; + await client.send('IO.close', {handle}); + this.push(null); + } + } catch (error) { + if (isErrorLike(error)) { + this.destroy(error); + return; + } + throw error; } }, }); diff --git a/packages/puppeteer-core/src/node/BrowserFetcher.ts b/packages/puppeteer-core/src/node/BrowserFetcher.ts deleted file mode 100644 index 24c6a9364ad..00000000000 --- a/packages/puppeteer-core/src/node/BrowserFetcher.ts +++ /dev/null @@ -1,724 +0,0 @@ -/** - * Copyright 2017 Google Inc. All rights reserved. - * - * 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. - */ - -import {exec as execChildProcess} from 'child_process'; -import {createReadStream, createWriteStream, existsSync, readdirSync} from 'fs'; -import {chmod, mkdir, readdir, unlink} from 'fs/promises'; -import http from 'http'; -import https from 'https'; -import os from 'os'; -import path from 'path'; -import URL from 'url'; -import {promisify, format} from 'util'; - -import extractZip from 'extract-zip'; -import createHttpsProxyAgent, { - HttpsProxyAgent, - HttpsProxyAgentOptions, -} from 'https-proxy-agent'; -import {getProxyForUrl} from 'proxy-from-env'; -import tar from 'tar-fs'; -import bzip from 'unbzip2-stream'; - -import {debug} from '../common/Debug.js'; -import {Product} from '../common/Product.js'; -import {assert} from '../util/assert.js'; - -import {rm} from './util/fs.js'; - -const debugFetcher = debug('puppeteer:fetcher'); - -const downloadURLs: Record>> = { - chrome: { - linux: '%s/chromium-browser-snapshots/Linux_x64/%d/%s.zip', - mac: '%s/chromium-browser-snapshots/Mac/%d/%s.zip', - mac_arm: '%s/chromium-browser-snapshots/Mac_Arm/%d/%s.zip', - win32: '%s/chromium-browser-snapshots/Win/%d/%s.zip', - win64: '%s/chromium-browser-snapshots/Win_x64/%d/%s.zip', - }, - firefox: { - linux: '%s/firefox-%s.en-US.%s-x86_64.tar.bz2', - mac: '%s/firefox-%s.en-US.%s.dmg', - win32: '%s/firefox-%s.en-US.%s.zip', - win64: '%s/firefox-%s.en-US.%s.zip', - }, -}; - -const browserConfig = { - chrome: { - host: 'https://storage.googleapis.com', - }, - firefox: { - host: 'https://archive.mozilla.org/pub/firefox/nightly/latest-mozilla-central', - }, -} as const; - -const exec = promisify(execChildProcess); - -/** - * Supported platforms. - * - * @public - */ -export type Platform = 'linux' | 'mac' | 'mac_arm' | 'win32' | 'win64'; - -function archiveName( - product: Product, - platform: Platform, - revision: string -): string { - switch (product) { - case 'chrome': - switch (platform) { - case 'linux': - return 'chrome-linux'; - case 'mac_arm': - case 'mac': - return 'chrome-mac'; - case 'win32': - case 'win64': - // Windows archive name changed at r591479. - return parseInt(revision, 10) > 591479 - ? 'chrome-win' - : 'chrome-win32'; - } - case 'firefox': - return platform; - } -} - -function downloadURL( - product: Product, - platform: Platform, - host: string, - revision: string -): string { - const url = format( - downloadURLs[product][platform], - host, - revision, - archiveName(product, platform, revision) - ); - return url; -} - -function handleArm64(): void { - let exists = existsSync('/usr/bin/chromium-browser'); - if (exists) { - return; - } - exists = existsSync('/usr/bin/chromium'); - if (exists) { - return; - } - console.error( - 'The chromium binary is not available for arm64.' + - '\nIf you are on Ubuntu, you can install with: ' + - '\n\n sudo apt install chromium\n' + - '\n\n sudo apt install chromium-browser\n' - ); - throw new Error(); -} - -/** - * @public - */ -export interface BrowserFetcherOptions { - /** - * Determines the path to download browsers to. - */ - path: string; - /** - * Determines which platform the browser will be suited for. - * - * @defaultValue **Auto-detected.** - */ - platform?: Platform; - /** - * Determines which product the {@link BrowserFetcher} is for. - * - * @defaultValue `chrome` - */ - product?: 'chrome' | 'firefox'; - /** - * Determines the host that will be used for downloading. - * - * @defaultValue Either - * - * - https://storage.googleapis.com or - * - https://archive.mozilla.org/pub/firefox/nightly/latest-mozilla-central - * - */ - host?: string; - - /** - * Enables the use of the Chromium binary for macOS ARM. - * - * @experimental - */ - useMacOSARMBinary?: boolean; -} - -/** - * @public - */ -export interface BrowserFetcherRevisionInfo { - folderPath: string; - executablePath: string; - url: string; - local: boolean; - revision: string; - product: string; -} - -/** - * BrowserFetcher can download and manage different versions of Chromium and - * Firefox. - * - * @remarks - * BrowserFetcher operates on revision strings that specify a precise version of - * Chromium, e.g. `"533271"`. Revision strings can be obtained from - * {@link http://omahaproxy.appspot.com/ | omahaproxy.appspot.com}. For Firefox, - * BrowserFetcher downloads Firefox Nightly and operates on version numbers such - * as `"75"`. - * - * @remarks - * The default constructed fetcher will always be for Chromium unless otherwise - * specified. - * - * @remarks - * BrowserFetcher is not designed to work concurrently with other instances of - * BrowserFetcher that share the same downloads directory. - * - * @example - * An example of using BrowserFetcher to download a specific version of Chromium - * and running Puppeteer against it: - * - * ```ts - * const browserFetcher = new BrowserFetcher({path: 'path/to/download/folder'}); - * const revisionInfo = await browserFetcher.download('533271'); - * const browser = await puppeteer.launch({ - * executablePath: revisionInfo.executablePath, - * }); - * ``` - * - * @public - */ - -export class BrowserFetcher { - #product: Product; - #downloadPath: string; - #downloadHost: string; - #platform: Platform; - - /** - * Constructs a browser fetcher for the given options. - */ - constructor(options: BrowserFetcherOptions) { - this.#product = options.product ?? 'chrome'; - this.#downloadPath = options.path; - this.#downloadHost = options.host ?? browserConfig[this.#product].host; - - if (options.platform) { - this.#platform = options.platform; - } else { - const platform = os.platform(); - switch (platform) { - case 'darwin': - switch (this.#product) { - case 'chrome': - this.#platform = - os.arch() === 'arm64' && options.useMacOSARMBinary - ? 'mac_arm' - : 'mac'; - break; - case 'firefox': - this.#platform = 'mac'; - break; - } - break; - case 'linux': - this.#platform = 'linux'; - break; - case 'win32': - this.#platform = - os.arch() === 'x64' || - // Windows 11 for ARM supports x64 emulation - (os.arch() === 'arm64' && isWindows11(os.release())) - ? 'win64' - : 'win32'; - return; - default: - assert(false, 'Unsupported platform: ' + platform); - } - } - - assert( - downloadURLs[this.#product][this.#platform], - 'Unsupported platform: ' + this.#platform - ); - } - - /** - * Returns the current `Platform`, which is one of `mac`, `linux`, - * `win32` or `win64`. - */ - platform(): Platform { - return this.#platform; - } - - /** - * Returns the current `Product`, which is one of `chrome` or - * `firefox`. - */ - product(): Product { - return this.#product; - } - - /** - * The download host being used. - */ - host(): string { - return this.#downloadHost; - } - - /** - * Initiates a HEAD request to check if the revision is available. - * @remarks - * This method is affected by the current `product`. - * @param revision - The revision to check availability for. - * @returns A promise that resolves to `true` if the revision could be downloaded - * from the host. - */ - canDownload(revision: string): Promise { - const url = downloadURL( - this.#product, - this.#platform, - this.#downloadHost, - revision - ); - return new Promise(resolve => { - const request = httpRequest( - url, - 'HEAD', - response => { - resolve(response.statusCode === 200); - }, - false - ); - request.on('error', error => { - console.error(error); - resolve(false); - }); - }); - } - - /** - * Initiates a GET request to download the revision from the host. - * @remarks - * This method is affected by the current `product`. - * @param revision - The revision to download. - * @param progressCallback - A function that will be called with two arguments: - * How many bytes have been downloaded and the total number of bytes of the download. - * @returns A promise with revision information when the revision is downloaded - * and extracted. - */ - async download( - revision: string, - progressCallback: (x: number, y: number) => void = (): void => {} - ): Promise { - const url = downloadURL( - this.#product, - this.#platform, - this.#downloadHost, - revision - ); - const fileName = url.split('/').pop(); - assert(fileName, `A malformed download URL was found: ${url}.`); - const archivePath = path.join(this.#downloadPath, fileName); - const outputPath = this.#getFolderPath(revision); - if (existsSync(outputPath)) { - return this.revisionInfo(revision); - } - if (!existsSync(this.#downloadPath)) { - await mkdir(this.#downloadPath, {recursive: true}); - } - - // Use system Chromium builds on Linux ARM devices - if (os.platform() === 'linux' && os.arch() === 'arm64') { - handleArm64(); - return; - } - try { - await _downloadFile(url, archivePath, progressCallback); - await install(archivePath, outputPath); - } finally { - if (existsSync(archivePath)) { - await unlink(archivePath); - } - } - const revisionInfo = this.revisionInfo(revision); - if (revisionInfo) { - await chmod(revisionInfo.executablePath, 0o755); - } - return revisionInfo; - } - - /** - * @remarks - * This method is affected by the current `product`. - * @returns A list of all revision strings (for the current `product`) - * available locally on disk. - */ - localRevisions(): string[] { - if (!existsSync(this.#downloadPath)) { - return []; - } - const fileNames = readdirSync(this.#downloadPath); - return fileNames - .map(fileName => { - return parseFolderPath(this.#product, fileName); - }) - .filter((entry): entry is Exclude => { - return (entry && entry.platform === this.#platform) ?? false; - }) - .map(entry => { - return entry.revision; - }); - } - - /** - * @remarks - * This method is affected by the current `product`. - * @param revision - A revision to remove for the current `product`. - * @returns A promise that resolves when the revision has been removed or - * throws if the revision has not been downloaded. - */ - async remove(revision: string): Promise { - const folderPath = this.#getFolderPath(revision); - assert( - existsSync(folderPath), - `Failed to remove: revision ${revision} is not downloaded` - ); - await rm(folderPath); - } - - /** - * @param revision - The revision to get info for. - * @returns The revision info for the given revision. - */ - revisionInfo(revision: string): BrowserFetcherRevisionInfo { - const folderPath = this.#getFolderPath(revision); - let executablePath = ''; - switch (this.#product) { - case 'chrome': - switch (this.#platform) { - case 'mac': - case 'mac_arm': - executablePath = path.join( - folderPath, - archiveName(this.#product, this.#platform, revision), - 'Chromium.app', - 'Contents', - 'MacOS', - 'Chromium' - ); - break; - case 'linux': - executablePath = path.join( - folderPath, - archiveName(this.#product, this.#platform, revision), - 'chrome' - ); - break; - case 'win32': - case 'win64': - executablePath = path.join( - folderPath, - archiveName(this.#product, this.#platform, revision), - 'chrome.exe' - ); - break; - } - break; - case 'firefox': - switch (this.#platform) { - case 'mac': - case 'mac_arm': - executablePath = path.join( - folderPath, - 'Firefox Nightly.app', - 'Contents', - 'MacOS', - 'firefox' - ); - break; - case 'linux': - executablePath = path.join(folderPath, 'firefox', 'firefox'); - break; - case 'win32': - case 'win64': - executablePath = path.join(folderPath, 'firefox', 'firefox.exe'); - break; - } - } - - const url = downloadURL( - this.#product, - this.#platform, - this.#downloadHost, - revision - ); - const local = existsSync(folderPath); - debugFetcher({ - revision, - executablePath, - folderPath, - local, - url, - product: this.#product, - }); - return { - revision, - executablePath, - folderPath, - local, - url, - product: this.#product, - }; - } - - #getFolderPath(revision: string): string { - return path.resolve(this.#downloadPath, `${this.#platform}-${revision}`); - } - - /** - * @internal - */ - getDownloadPath(): string { - return this.#downloadPath; - } -} - -function parseFolderPath( - product: Product, - folderPath: string -): {product: string; platform: string; revision: string} | undefined { - const name = path.basename(folderPath); - const splits = name.split('-'); - if (splits.length !== 2) { - return; - } - const [platform, revision] = splits; - if (!revision || !platform || !(platform in downloadURLs[product])) { - return; - } - return {product, platform, revision}; -} - -/** - * Windows 11 is identified by 10.0.22000 or greater - * @internal - */ -function isWindows11(version: string): boolean { - const parts = version.split('.'); - if (parts.length > 2) { - const major = parseInt(parts[0] as string, 10); - const minor = parseInt(parts[1] as string, 10); - const patch = parseInt(parts[2] as string, 10); - return ( - major > 10 || - (major === 10 && minor > 0) || - (major === 10 && minor === 0 && patch >= 22000) - ); - } - return false; -} - -/** - * @internal - */ -function _downloadFile( - url: string, - destinationPath: string, - progressCallback?: (x: number, y: number) => void -): Promise { - debugFetcher(`Downloading binary from ${url}`); - let fulfill: (value: void | PromiseLike) => void; - let reject: (err: Error) => void; - const promise = new Promise((x, y) => { - fulfill = x; - reject = y; - }); - - let downloadedBytes = 0; - let totalBytes = 0; - - const request = httpRequest(url, 'GET', response => { - if (response.statusCode !== 200) { - const error = new Error( - `Download failed: server returned code ${response.statusCode}. URL: ${url}` - ); - // consume response data to free up memory - response.resume(); - reject(error); - return; - } - const file = createWriteStream(destinationPath); - file.on('finish', () => { - return fulfill(); - }); - file.on('error', error => { - return reject(error); - }); - response.pipe(file); - totalBytes = parseInt(response.headers['content-length']!, 10); - if (progressCallback) { - response.on('data', onData); - } - }); - request.on('error', error => { - return reject(error); - }); - return promise; - - function onData(chunk: string): void { - downloadedBytes += chunk.length; - progressCallback!(downloadedBytes, totalBytes); - } -} - -async function install(archivePath: string, folderPath: string): Promise { - debugFetcher(`Installing ${archivePath} to ${folderPath}`); - if (archivePath.endsWith('.zip')) { - await extractZip(archivePath, {dir: folderPath}); - } else if (archivePath.endsWith('.tar.bz2')) { - await extractTar(archivePath, folderPath); - } else if (archivePath.endsWith('.dmg')) { - await mkdir(folderPath); - await installDMG(archivePath, folderPath); - } else { - throw new Error(`Unsupported archive format: ${archivePath}`); - } -} - -/** - * @internal - */ -function extractTar(tarPath: string, folderPath: string): Promise { - return new Promise((fulfill, reject) => { - const tarStream = tar.extract(folderPath); - tarStream.on('error', reject); - tarStream.on('finish', fulfill); - const readStream = createReadStream(tarPath); - readStream.pipe(bzip()).pipe(tarStream); - }); -} - -/** - * @internal - */ -async function installDMG(dmgPath: string, folderPath: string): Promise { - const {stdout} = await exec( - `hdiutil attach -nobrowse -noautoopen "${dmgPath}"` - ); - - const volumes = stdout.match(/\/Volumes\/(.*)/m); - if (!volumes) { - throw new Error(`Could not find volume path in ${stdout}`); - } - const mountPath = volumes[0]!; - - try { - const fileNames = await readdir(mountPath); - const appName = fileNames.find(item => { - return typeof item === 'string' && item.endsWith('.app'); - }); - if (!appName) { - throw new Error(`Cannot find app in ${mountPath}`); - } - const mountedPath = path.join(mountPath!, appName); - - debugFetcher(`Copying ${mountedPath} to ${folderPath}`); - await exec(`cp -R "${mountedPath}" "${folderPath}"`); - } finally { - debugFetcher(`Unmounting ${mountPath}`); - await exec(`hdiutil detach "${mountPath}" -quiet`); - } -} - -function httpRequest( - url: string, - method: string, - response: (x: http.IncomingMessage) => void, - keepAlive = true -): http.ClientRequest { - const urlParsed = URL.parse(url); - - type Options = Partial & { - method?: string; - agent?: HttpsProxyAgent; - rejectUnauthorized?: boolean; - headers?: http.OutgoingHttpHeaders | undefined; - }; - - let options: Options = { - ...urlParsed, - method, - headers: keepAlive ? {Connection: 'keep-alive'} : undefined, - }; - - const proxyURL = getProxyForUrl(url); - if (proxyURL) { - if (url.startsWith('http:')) { - const proxy = URL.parse(proxyURL); - options = { - path: options.href, - host: proxy.hostname, - port: proxy.port, - }; - } else { - const parsedProxyURL = URL.parse(proxyURL); - - const proxyOptions = { - ...parsedProxyURL, - secureProxy: parsedProxyURL.protocol === 'https:', - } as HttpsProxyAgentOptions; - - options.agent = createHttpsProxyAgent(proxyOptions); - options.rejectUnauthorized = false; - } - } - - const requestCallback = (res: http.IncomingMessage): void => { - if ( - res.statusCode && - res.statusCode >= 300 && - res.statusCode < 400 && - res.headers.location - ) { - httpRequest(res.headers.location, method, response); - } else { - response(res); - } - }; - const request = - options.protocol === 'https:' - ? https.request(options, requestCallback) - : http.request(options, requestCallback); - request.end(); - return request; -} diff --git a/packages/puppeteer-core/src/node/ChromeLauncher.ts b/packages/puppeteer-core/src/node/ChromeLauncher.ts index af0b89096df..9594ed33db0 100644 --- a/packages/puppeteer-core/src/node/ChromeLauncher.ts +++ b/packages/puppeteer-core/src/node/ChromeLauncher.ts @@ -179,7 +179,8 @@ export class ChromeLauncher extends ProductLauncher { '--disable-dev-shm-usage', '--disable-extensions', // AcceptCHFrame disabled because of crbug.com/1348106. - '--disable-features=Translate,BackForwardCache,AcceptCHFrame,MediaRouter,OptimizationHints', + // DIPS is disabled because of crbug.com/1439578. TODO: enable after M115. + '--disable-features=Translate,BackForwardCache,AcceptCHFrame,MediaRouter,OptimizationHints,DIPS', '--disable-hang-monitor', '--disable-ipc-flooding-protection', '--disable-popup-blocking', diff --git a/packages/puppeteer-core/src/node/FirefoxLauncher.ts b/packages/puppeteer-core/src/node/FirefoxLauncher.ts index 4eeb424bc7a..004d78bd7fb 100644 --- a/packages/puppeteer-core/src/node/FirefoxLauncher.ts +++ b/packages/puppeteer-core/src/node/FirefoxLauncher.ts @@ -19,7 +19,13 @@ import {rename, unlink, mkdtemp} from 'fs/promises'; import os from 'os'; import path from 'path'; -import {Browser as SupportedBrowsers, createProfile} from '@puppeteer/browsers'; +import { + Browser as SupportedBrowsers, + createProfile, + Cache, + detectBrowserPlatform, + Browser, +} from '@puppeteer/browsers'; import {debugError} from '../common/util.js'; import {assert} from '../util/assert.js'; @@ -164,13 +170,15 @@ export class FirefoxLauncher extends ProductLauncher { override executablePath(): string { // replace 'latest' placeholder with actual downloaded revision if (this.puppeteer.browserRevision === 'latest') { - const browserFetcher = this.puppeteer.createBrowserFetcher({ - product: this.product, - path: this.puppeteer.defaultDownloadPath!, + const cache = new Cache(this.puppeteer.defaultDownloadPath!); + const installedFirefox = cache.getInstalledBrowsers().find(browser => { + return ( + browser.platform === detectBrowserPlatform() && + browser.browser === Browser.FIREFOX + ); }); - const localRevisions = browserFetcher.localRevisions(); - if (localRevisions[0]) { - this.actualBrowserRevision = localRevisions[0]; + if (installedFirefox) { + this.actualBrowserRevision = installedFirefox.buildId; } } return this.resolveExecutablePath(); diff --git a/packages/puppeteer-core/src/node/ProductLauncher.ts b/packages/puppeteer-core/src/node/ProductLauncher.ts index 719051930f6..9b92772fab8 100644 --- a/packages/puppeteer-core/src/node/ProductLauncher.ts +++ b/packages/puppeteer-core/src/node/ProductLauncher.ts @@ -14,14 +14,16 @@ * limitations under the License. */ import {existsSync} from 'fs'; -import os, {tmpdir} from 'os'; +import {tmpdir} from 'os'; import {join} from 'path'; import { + Browser as InstalledBrowser, CDP_WEBSOCKET_ENDPOINT_REGEX, launch, TimeoutError as BrowsersTimeoutError, WEBDRIVER_BIDI_WEBSOCKET_ENDPOINT_REGEX, + computeExecutablePath, } from '@puppeteer/browsers'; import {Browser, BrowserCloseCallback} from '../api/Browser.js'; @@ -392,7 +394,7 @@ export class ProductLauncher { * @internal */ protected resolveExecutablePath(): string { - const executablePath = this.puppeteer.configuration.executablePath; + let executablePath = this.puppeteer.configuration.executablePath; if (executablePath) { if (!existsSync(executablePath)) { throw new Error( @@ -402,34 +404,32 @@ export class ProductLauncher { return executablePath; } - const ubuntuChromiumPath = '/usr/bin/chromium-browser'; - if ( - this.product === 'chrome' && - os.platform() !== 'darwin' && - os.arch() === 'arm64' && - existsSync(ubuntuChromiumPath) - ) { - return ubuntuChromiumPath; + function productToBrowser(product?: Product) { + switch (product) { + case 'chrome': + return InstalledBrowser.CHROME; + case 'firefox': + return InstalledBrowser.FIREFOX; + } + return InstalledBrowser.CHROME; } - const browserFetcher = this.puppeteer.createBrowserFetcher({ - product: this.product, - path: this.puppeteer.defaultDownloadPath!, + executablePath = computeExecutablePath({ + cacheDir: this.puppeteer.defaultDownloadPath!, + browser: productToBrowser(this.product), + buildId: this.puppeteer.browserRevision, }); - const revisionInfo = browserFetcher.revisionInfo( - this.puppeteer.browserRevision - ); - if (!revisionInfo.local) { + if (!existsSync(executablePath)) { if (this.puppeteer.configuration.browserRevision) { throw new Error( - `Tried to find the browser at the configured path (${revisionInfo.executablePath}) for revision ${this.puppeteer.browserRevision}, but no executable was found.` + `Tried to find the browser at the configured path (${executablePath}) for revision ${this.puppeteer.browserRevision}, but no executable was found.` ); } switch (this.product) { case 'chrome': throw new Error( - `Could not find Chromium (rev. ${this.puppeteer.browserRevision}). This can occur if either\n` + + `Could not find Chrome (ver. ${this.puppeteer.browserRevision}). This can occur if either\n` + ' 1. you did not perform an installation before running the script (e.g. `npm install`) or\n' + ` 2. your cache path is incorrectly configured (which is: ${this.puppeteer.configuration.cacheDirectory}).\n` + 'For (2), check out our guide on configuring puppeteer at https://pptr.dev/guides/configuration.' @@ -443,6 +443,6 @@ export class ProductLauncher { ); } } - return revisionInfo.executablePath; + return executablePath; } } diff --git a/packages/puppeteer-core/src/node/PuppeteerNode.ts b/packages/puppeteer-core/src/node/PuppeteerNode.ts index fb61161c92b..c6667eb28f9 100644 --- a/packages/puppeteer-core/src/node/PuppeteerNode.ts +++ b/packages/puppeteer-core/src/node/PuppeteerNode.ts @@ -14,8 +14,6 @@ * limitations under the License. */ -import {join} from 'path'; - import {Browser} from '../api/Browser.js'; import {BrowserConnectOptions} from '../common/BrowserConnector.js'; import {Configuration} from '../common/Configuration.js'; @@ -27,7 +25,6 @@ import { } from '../common/Puppeteer.js'; import {PUPPETEER_REVISIONS} from '../revisions.js'; -import {BrowserFetcher, BrowserFetcherOptions} from './BrowserFetcher.js'; import {ChromeLauncher} from './ChromeLauncher.js'; import {FirefoxLauncher} from './FirefoxLauncher.js'; import { @@ -116,7 +113,7 @@ export class PuppeteerNode extends Puppeteer { break; default: this.configuration.defaultProduct = 'chrome'; - this.defaultBrowserRevision = PUPPETEER_REVISIONS.chromium; + this.defaultBrowserRevision = PUPPETEER_REVISIONS.chrome; break; } @@ -124,7 +121,6 @@ export class PuppeteerNode extends Puppeteer { this.launch = this.launch.bind(this); this.executablePath = this.executablePath.bind(this); this.defaultArgs = this.defaultArgs.bind(this); - this.createBrowserFetcher = this.createBrowserFetcher.bind(this); } /** @@ -157,9 +153,9 @@ export class PuppeteerNode extends Puppeteer { * * @remarks * Puppeteer can also be used to control the Chrome browser, but it works best - * with the version of Chromium downloaded by default by Puppeteer. There is - * no guarantee it will work with any other version. If Google Chrome (rather - * than Chromium) is preferred, a + * with the version of Chrome for Testing downloaded by default. + * There is no guarantee it will work with any other version. If Google Chrome + * (rather than Chrome for Testing) is preferred, a * {@link https://www.google.com/chrome/browser/canary.html | Chrome Canary} * or * {@link https://www.chromium.org/getting-involved/dev-channel | Dev Channel} @@ -167,7 +163,9 @@ export class PuppeteerNode extends Puppeteer { * {@link https://www.howtogeek.com/202825/what%E2%80%99s-the-difference-between-chromium-and-chrome/ | this article} * for a description of the differences between Chromium and Chrome. * {@link https://chromium.googlesource.com/chromium/src/+/lkgr/docs/chromium_browser_vs_google_chrome.md | This article} - * describes some differences for Linux users. + * describes some differences for Linux users. See + * {@link https://goo.gle/chrome-for-testing | this doc} for the description + * of Chrome for Testing. * * @param options - Options to configure launching behavior. */ @@ -189,7 +187,7 @@ export class PuppeteerNode extends Puppeteer { } switch (this.lastLaunchedProduct) { case 'chrome': - this.defaultBrowserRevision = PUPPETEER_REVISIONS.chromium; + this.defaultBrowserRevision = PUPPETEER_REVISIONS.chrome; this.#_launcher = new ChromeLauncher(this); break; case 'firefox': @@ -227,10 +225,7 @@ export class PuppeteerNode extends Puppeteer { * @internal */ get defaultDownloadPath(): string | undefined { - return ( - this.configuration.downloadPath ?? - join(this.configuration.cacheDirectory!, this.product) - ); + return this.configuration.downloadPath ?? this.configuration.cacheDirectory; } /** @@ -269,39 +264,4 @@ export class PuppeteerNode extends Puppeteer { defaultArgs(options: BrowserLaunchArgumentOptions = {}): string[] { return this.#launcher.defaultArgs(options); } - - /** - * @param options - Set of configurable options to specify the settings of the - * BrowserFetcher. - * - * @remarks - * If you are using `puppeteer-core`, do not use this method. Just - * construct {@link BrowserFetcher} manually. - * - * @returns A new BrowserFetcher instance. - */ - createBrowserFetcher( - options: Partial = {} - ): BrowserFetcher { - const downloadPath = this.defaultDownloadPath; - if (!options.path && downloadPath) { - options.path = downloadPath; - } - if (!options.path) { - throw new Error('A `path` must be specified for `puppeteer-core`.'); - } - if ( - !('useMacOSARMBinary' in options) && - this.configuration.experiments?.macArmChromiumEnabled - ) { - options.useMacOSARMBinary = true; - } - if (!('host' in options) && this.configuration.downloadHost) { - options.host = this.configuration.downloadHost; - } - if (!('product' in options) && this.configuration.defaultProduct) { - options.product = this.configuration.defaultProduct; - } - return new BrowserFetcher(options as BrowserFetcherOptions); - } } diff --git a/packages/puppeteer-core/src/node/node.ts b/packages/puppeteer-core/src/node/node.ts index 6de393a4f32..da815faf166 100644 --- a/packages/puppeteer-core/src/node/node.ts +++ b/packages/puppeteer-core/src/node/node.ts @@ -14,7 +14,6 @@ * limitations under the License. */ -export * from './BrowserFetcher.js'; export * from './ChromeLauncher.js'; export * from './FirefoxLauncher.js'; export * from './LaunchOptions.js'; diff --git a/packages/puppeteer-core/src/puppeteer-core.ts b/packages/puppeteer-core/src/puppeteer-core.ts index 787d83c2d5f..08cb8092a51 100644 --- a/packages/puppeteer-core/src/puppeteer-core.ts +++ b/packages/puppeteer-core/src/puppeteer-core.ts @@ -41,10 +41,6 @@ export const { * @public */ connect, - /** - * @public - */ - createBrowserFetcher, /** * @public */ diff --git a/packages/puppeteer-core/src/revisions.ts b/packages/puppeteer-core/src/revisions.ts index 6198306c498..151f7b4b579 100644 --- a/packages/puppeteer-core/src/revisions.ts +++ b/packages/puppeteer-core/src/revisions.ts @@ -18,6 +18,6 @@ * @internal */ export const PUPPETEER_REVISIONS = Object.freeze({ - chromium: '1108766', + chrome: '112.0.5615.121', firefox: 'latest', }); diff --git a/packages/puppeteer-core/tools/ensure-correct-devtools-protocol-package.ts b/packages/puppeteer-core/tools/ensure-correct-devtools-protocol-package.ts index f28d890beb2..5c0d74cbcd5 100644 --- a/packages/puppeteer-core/tools/ensure-correct-devtools-protocol-package.ts +++ b/packages/puppeteer-core/tools/ensure-correct-devtools-protocol-package.ts @@ -16,21 +16,21 @@ /** * This script ensures that the pinned version of devtools-protocol in - * package.json is the right version for the current revision of Chromium that + * package.json is the right version for the current revision of Chrome that * Puppeteer ships with. * * The devtools-protocol package publisher runs every hour and checks if there * are protocol changes. If there are, it will be versioned with the revision * number of the commit that last changed the .pdl files. * - * Chromium branches/releases are figured out at a later point in time, so it's - * not true that each Chromium revision will have an exact matching revision + * Chrome branches/releases are figured out at a later point in time, so it's + * not true that each Chrome revision will have an exact matching revision * version of devtools-protocol. To ensure we're using a devtools-protocol that * is aligned with our revision, we want to find the largest package number * that's \<= the revision that Puppeteer is using. * * This script uses npm's `view` function to list all versions in a range and - * find the one closest to our Chromium revision. + * find the one closest to our Chrome revision. */ // eslint-disable-next-line import/extensions @@ -39,46 +39,59 @@ import {execSync} from 'child_process'; import packageJson from '../package.json'; import {PUPPETEER_REVISIONS} from '../src/revisions.js'; -const currentProtocolPackageInstalledVersion = - packageJson.dependencies['devtools-protocol']; +async function main() { + const currentProtocolPackageInstalledVersion = + packageJson.dependencies['devtools-protocol']; -/** - * Ensure that the devtools-protocol version is pinned. - */ -if (/^[^0-9]/.test(currentProtocolPackageInstalledVersion)) { - console.log( - `ERROR: devtools-protocol package is not pinned to a specific version.\n` + /** + * Ensure that the devtools-protocol version is pinned. + */ + if (/^[^0-9]/.test(currentProtocolPackageInstalledVersion)) { + console.log( + `ERROR: devtools-protocol package is not pinned to a specific version.\n` + ); + process.exit(1); + } + + const chromeVersion = PUPPETEER_REVISIONS.chrome; + // find the right revision for our Chrome version. + const req = await fetch( + `https://chromiumdash.appspot.com/fetch_releases?channel=stable` ); - process.exit(1); -} + const stableReleases = await req.json(); + const chromeRevision = stableReleases.find(release => { + return release.version === chromeVersion; + }).chromium_main_branch_position; + console.log(`Revisions for ${chromeVersion}: ${chromeRevision}`); -// find the right revision for our Chromium revision + const command = `npm view "devtools-protocol@<=0.0.${chromeRevision}" version | tail -1`; -const command = `npm view "devtools-protocol@<=0.0.${PUPPETEER_REVISIONS.chromium}" version | tail -1`; + console.log( + 'Checking npm for devtools-protocol revisions:\n', + `'${command}'`, + '\n' + ); -console.log( - 'Checking npm for devtools-protocol revisions:\n', - `'${command}'`, - '\n' -); + const output = execSync(command, { + encoding: 'utf8', + }); -const output = execSync(command, { - encoding: 'utf8', -}); + const bestRevisionFromNpm = output.split(' ')[1]!.replace(/'|\n/g, ''); -const bestRevisionFromNpm = output.split(' ')[1]!.replace(/'|\n/g, ''); + if (currentProtocolPackageInstalledVersion !== bestRevisionFromNpm) { + console.log(`ERROR: bad devtools-protocol revision detected: -if (currentProtocolPackageInstalledVersion !== bestRevisionFromNpm) { - console.log(`ERROR: bad devtools-protocol revision detected: - - Current Puppeteer Chromium revision: ${PUPPETEER_REVISIONS.chromium} + Current Puppeteer Chrome revision: ${chromeRevision} Current devtools-protocol version in package.json: ${currentProtocolPackageInstalledVersion} Expected devtools-protocol version: ${bestRevisionFromNpm}`); - process.exit(1); + process.exit(1); + } + + console.log( + `Correct devtools-protocol version found (${bestRevisionFromNpm}).` + ); + process.exit(0); } -console.log( - `Correct devtools-protocol version found (${bestRevisionFromNpm}).` -); -process.exit(0); +void main(); diff --git a/packages/puppeteer/src/getConfiguration.ts b/packages/puppeteer/src/getConfiguration.ts index 33c776bbeca..d682bac4de4 100644 --- a/packages/puppeteer/src/getConfiguration.ts +++ b/packages/puppeteer/src/getConfiguration.ts @@ -47,16 +47,12 @@ export const getConfiguration = (): Configuration => { process.env['PUPPETEER_SKIP_DOWNLOAD'] ?? process.env['npm_config_puppeteer_skip_download'] ?? process.env['npm_package_config_puppeteer_skip_download'] ?? - process.env['PUPPETEER_SKIP_CHROMIUM_DOWNLOAD'] ?? - process.env['npm_config_puppeteer_skip_chromium_download'] ?? - process.env['npm_package_config_puppeteer_skip_chromium_download'] ?? configuration.skipDownload ); // Prepare variables used in browser downloading if (!configuration.skipDownload) { configuration.browserRevision = - process.env['PUPPETEER_CHROMIUM_REVISION'] ?? process.env['PUPPETEER_BROWSER_REVISION'] ?? process.env['npm_config_puppeteer_browser_revision'] ?? process.env['npm_package_config_puppeteer_browser_revision'] ?? @@ -86,14 +82,6 @@ export const getConfiguration = (): Configuration => { configuration.temporaryDirectory; configuration.experiments ??= {}; - configuration.experiments.macArmChromiumEnabled = Boolean( - process.env['PUPPETEER_EXPERIMENTAL_CHROMIUM_MAC_ARM'] ?? - process.env['npm_config_puppeteer_experimental_chromium_mac_arm'] ?? - process.env[ - 'npm_package_config_puppeteer_experimental_chromium_mac_arm' - ] ?? - configuration.experiments.macArmChromiumEnabled - ); configuration.logLevel = (process.env['PUPPETEER_LOGLEVEL'] ?? process.env['npm_config_LOGLEVEL'] ?? diff --git a/packages/puppeteer/src/node/install.ts b/packages/puppeteer/src/node/install.ts index 9ee970ae260..f3cd7587b27 100644 --- a/packages/puppeteer/src/node/install.ts +++ b/packages/puppeteer/src/node/install.ts @@ -20,7 +20,6 @@ import { resolveBuildId, makeProgressCallback, detectBrowserPlatform, - BrowserPlatform, } from '@puppeteer/browsers'; import {Product} from 'puppeteer-core'; import {PUPPETEER_REVISIONS} from 'puppeteer-core/internal/revisions.js'; @@ -31,8 +30,7 @@ import {getConfiguration} from '../getConfiguration.js'; * @internal */ const supportedProducts = { - chromium: 'Chromium', - chrome: 'Chromium', + chrome: 'Chrome', firefox: 'Firefox Nightly', } as const; @@ -48,42 +46,18 @@ export async function downloadBrowser(): Promise { return; } - let downloadHost = configuration.downloadHost; + const downloadHost = configuration.downloadHost; - let platform = detectBrowserPlatform(); + const platform = detectBrowserPlatform(); if (!platform) { throw new Error('The current platform is not supported.'); } - // TODO: remove once Mac ARM is enabled by default for Puppeteer https://github.com/puppeteer/puppeteer/issues/9630. - if ( - platform === BrowserPlatform.MAC_ARM && - !configuration.experiments?.macArmChromiumEnabled - ) { - platform = BrowserPlatform.MAC; - } - const product = configuration.defaultProduct!; const browser = productToBrowser(product); - // TODO: PUPPETEER_REVISIONS should use Chrome and not Chromium. const unresolvedBuildId = - configuration.browserRevision || - PUPPETEER_REVISIONS[product === 'chrome' ? 'chromium' : 'firefox'] || - 'latest'; - - if (product === 'chrome' && downloadHost) { - // TODO: remove downloadHost in favour of baseDownloadUrl. The "host" of - // Firefox is already a URL and not a host. This would be a breaking change. - if ( - !downloadHost.endsWith('/chromium-browser-snapshots') && - !downloadHost.endsWith('/chromium-browser-snapshots/') - ) { - downloadHost += downloadHost.endsWith('/') - ? 'chromium-browser-snapshots' - : '/chromium-browser-snapshots'; - } - } + configuration.browserRevision || PUPPETEER_REVISIONS[product] || 'latest'; const buildId = await resolveBuildId(browser, platform, unresolvedBuildId); @@ -94,6 +68,8 @@ export async function downloadBrowser(): Promise { platform, buildId, downloadProgressCallback: makeProgressCallback(browser, buildId), + // TODO: remove downloadHost in favour of baseDownloadUrl. The "host" of + // Firefox is already a URL and not a host. This would be a breaking change. baseUrl: downloadHost, }); @@ -112,11 +88,11 @@ export async function downloadBrowser(): Promise { function productToBrowser(product?: Product) { switch (product) { case 'chrome': - return Browser.CHROMIUM; + return Browser.CHROME; case 'firefox': return Browser.FIREFOX; } - return Browser.CHROMIUM; + return Browser.CHROME; } /** diff --git a/packages/puppeteer/src/puppeteer.ts b/packages/puppeteer/src/puppeteer.ts index 6e95b78a1a1..1ba37feab03 100644 --- a/packages/puppeteer/src/puppeteer.ts +++ b/packages/puppeteer/src/puppeteer.ts @@ -37,10 +37,6 @@ export const { * @public */ connect, - /** - * @public - */ - createBrowserFetcher, /** * @public */ diff --git a/test-d/puppeteer.test-d.ts b/test-d/puppeteer.test-d.ts index 2138990d65a..11128f15f7d 100644 --- a/test-d/puppeteer.test-d.ts +++ b/test-d/puppeteer.test-d.ts @@ -1,6 +1,5 @@ import puppeteer, { connect, - createBrowserFetcher, defaultArgs, executablePath, launch, @@ -9,6 +8,5 @@ import {expectType} from 'tsd'; expectType(puppeteer.launch); expectType(puppeteer.connect); -expectType(puppeteer.createBrowserFetcher); expectType(puppeteer.defaultArgs); expectType(puppeteer.executablePath); diff --git a/test/TestExpectations.json b/test/TestExpectations.json index e305f5a2330..a9034f3f538 100644 --- a/test/TestExpectations.json +++ b/test/TestExpectations.json @@ -299,6 +299,12 @@ "parameters": ["webDriverBiDi"], "expectations": ["PASS"] }, + { + "testIdPattern": "[launcher.spec] Launcher specs Puppeteer Puppeteer.launch should work with no default arguments", + "platforms": ["darwin", "linux", "win32"], + "parameters": ["chrome"], + "expectations": ["SKIP"] + }, { "testIdPattern": "[navigation.spec] navigation Page.goto should fail when navigating to bad SSL", "platforms": ["darwin", "linux", "win32"], @@ -1013,18 +1019,6 @@ "parameters": ["cdp", "firefox"], "expectations": ["SKIP"] }, - { - "testIdPattern": "[launcher.spec] Launcher specs Puppeteer Puppeteer.executablePath when the product is chrome, platform is not darwin, and arch is arm64 and the executable does not exist does not return /usr/bin/chromium-browser", - "platforms": ["darwin", "linux", "win32"], - "parameters": ["cdp", "firefox"], - "expectations": ["SKIP"] - }, - { - "testIdPattern": "[launcher.spec] Launcher specs Puppeteer Puppeteer.executablePath when the product is chrome, platform is not darwin, and arch is arm64 and the executable exists returns /usr/bin/chromium-browser", - "platforms": ["darwin", "linux", "win32"], - "parameters": ["cdp", "firefox"], - "expectations": ["SKIP"] - }, { "testIdPattern": "[launcher.spec] Launcher specs Puppeteer Puppeteer.launch should be able to launch Chrome", "platforms": ["darwin", "linux", "win32"], diff --git a/test/golden-chromium/csscoverage-involved.txt b/test/golden-chrome/csscoverage-involved.txt similarity index 100% rename from test/golden-chromium/csscoverage-involved.txt rename to test/golden-chrome/csscoverage-involved.txt diff --git a/test/golden-chromium/grid-cell-0.png b/test/golden-chrome/grid-cell-0.png similarity index 100% rename from test/golden-chromium/grid-cell-0.png rename to test/golden-chrome/grid-cell-0.png diff --git a/test/golden-chromium/grid-cell-1.png b/test/golden-chrome/grid-cell-1.png similarity index 100% rename from test/golden-chromium/grid-cell-1.png rename to test/golden-chrome/grid-cell-1.png diff --git a/test/golden-chromium/grid-cell-2.png b/test/golden-chrome/grid-cell-2.png similarity index 100% rename from test/golden-chromium/grid-cell-2.png rename to test/golden-chrome/grid-cell-2.png diff --git a/test/golden-chromium/grid-cell-3.png b/test/golden-chrome/grid-cell-3.png similarity index 100% rename from test/golden-chromium/grid-cell-3.png rename to test/golden-chrome/grid-cell-3.png diff --git a/test/golden-chromium/jscoverage-involved.txt b/test/golden-chrome/jscoverage-involved.txt similarity index 100% rename from test/golden-chromium/jscoverage-involved.txt rename to test/golden-chrome/jscoverage-involved.txt diff --git a/test/golden-chromium/mock-binary-response.png b/test/golden-chrome/mock-binary-response.png similarity index 100% rename from test/golden-chromium/mock-binary-response.png rename to test/golden-chrome/mock-binary-response.png diff --git a/test/golden-chromium/screenshot-clip-odd-size.png b/test/golden-chrome/screenshot-clip-odd-size.png similarity index 100% rename from test/golden-chromium/screenshot-clip-odd-size.png rename to test/golden-chrome/screenshot-clip-odd-size.png diff --git a/test/golden-chromium/screenshot-clip-rect-scale2.png b/test/golden-chrome/screenshot-clip-rect-scale2.png similarity index 100% rename from test/golden-chromium/screenshot-clip-rect-scale2.png rename to test/golden-chrome/screenshot-clip-rect-scale2.png diff --git a/test/golden-chromium/screenshot-clip-rect.png b/test/golden-chrome/screenshot-clip-rect.png similarity index 100% rename from test/golden-chromium/screenshot-clip-rect.png rename to test/golden-chrome/screenshot-clip-rect.png diff --git a/test/golden-chromium/screenshot-element-bounding-box.png b/test/golden-chrome/screenshot-element-bounding-box.png similarity index 100% rename from test/golden-chromium/screenshot-element-bounding-box.png rename to test/golden-chrome/screenshot-element-bounding-box.png diff --git a/test/golden-chromium/screenshot-element-fractional-offset.png b/test/golden-chrome/screenshot-element-fractional-offset.png similarity index 100% rename from test/golden-chromium/screenshot-element-fractional-offset.png rename to test/golden-chrome/screenshot-element-fractional-offset.png diff --git a/test/golden-chromium/screenshot-element-fractional.png b/test/golden-chrome/screenshot-element-fractional.png similarity index 100% rename from test/golden-chromium/screenshot-element-fractional.png rename to test/golden-chrome/screenshot-element-fractional.png diff --git a/test/golden-chromium/screenshot-element-larger-than-viewport.png b/test/golden-chrome/screenshot-element-larger-than-viewport.png similarity index 100% rename from test/golden-chromium/screenshot-element-larger-than-viewport.png rename to test/golden-chrome/screenshot-element-larger-than-viewport.png diff --git a/test/golden-chromium/screenshot-element-padding-border.png b/test/golden-chrome/screenshot-element-padding-border.png similarity index 100% rename from test/golden-chromium/screenshot-element-padding-border.png rename to test/golden-chrome/screenshot-element-padding-border.png diff --git a/test/golden-chromium/screenshot-element-rotate.png b/test/golden-chrome/screenshot-element-rotate.png similarity index 100% rename from test/golden-chromium/screenshot-element-rotate.png rename to test/golden-chrome/screenshot-element-rotate.png diff --git a/test/golden-chromium/screenshot-element-scrolled-into-view.png b/test/golden-chrome/screenshot-element-scrolled-into-view.png similarity index 100% rename from test/golden-chromium/screenshot-element-scrolled-into-view.png rename to test/golden-chrome/screenshot-element-scrolled-into-view.png diff --git a/test/golden-chromium/screenshot-grid-fullpage.png b/test/golden-chrome/screenshot-grid-fullpage.png similarity index 100% rename from test/golden-chromium/screenshot-grid-fullpage.png rename to test/golden-chrome/screenshot-grid-fullpage.png diff --git a/test/golden-chromium/screenshot-offscreen-clip.png b/test/golden-chrome/screenshot-offscreen-clip.png similarity index 100% rename from test/golden-chromium/screenshot-offscreen-clip.png rename to test/golden-chrome/screenshot-offscreen-clip.png diff --git a/test/golden-chromium/screenshot-sanity.png b/test/golden-chrome/screenshot-sanity.png similarity index 100% rename from test/golden-chromium/screenshot-sanity.png rename to test/golden-chrome/screenshot-sanity.png diff --git a/test/golden-chromium/transparent.png b/test/golden-chrome/transparent.png similarity index 100% rename from test/golden-chromium/transparent.png rename to test/golden-chrome/transparent.png diff --git a/test/golden-chromium/vision-deficiency-achromatopsia.png b/test/golden-chrome/vision-deficiency-achromatopsia.png similarity index 100% rename from test/golden-chromium/vision-deficiency-achromatopsia.png rename to test/golden-chrome/vision-deficiency-achromatopsia.png diff --git a/test/golden-chromium/vision-deficiency-blurredVision.png b/test/golden-chrome/vision-deficiency-blurredVision.png similarity index 100% rename from test/golden-chromium/vision-deficiency-blurredVision.png rename to test/golden-chrome/vision-deficiency-blurredVision.png diff --git a/test/golden-chromium/vision-deficiency-deuteranopia.png b/test/golden-chrome/vision-deficiency-deuteranopia.png similarity index 100% rename from test/golden-chromium/vision-deficiency-deuteranopia.png rename to test/golden-chrome/vision-deficiency-deuteranopia.png diff --git a/test/golden-chromium/vision-deficiency-protanopia.png b/test/golden-chrome/vision-deficiency-protanopia.png similarity index 100% rename from test/golden-chromium/vision-deficiency-protanopia.png rename to test/golden-chrome/vision-deficiency-protanopia.png diff --git a/test/golden-chromium/vision-deficiency-tritanopia.png b/test/golden-chrome/vision-deficiency-tritanopia.png similarity index 100% rename from test/golden-chromium/vision-deficiency-tritanopia.png rename to test/golden-chrome/vision-deficiency-tritanopia.png diff --git a/test/golden-chromium/white.jpg b/test/golden-chrome/white.jpg similarity index 100% rename from test/golden-chromium/white.jpg rename to test/golden-chrome/white.jpg diff --git a/test/src/launcher.spec.ts b/test/src/launcher.spec.ts index 9f1d271bf8c..61249c0e071 100644 --- a/test/src/launcher.spec.ts +++ b/test/src/launcher.spec.ts @@ -14,14 +14,14 @@ * limitations under the License. */ import fs from 'fs'; -import {mkdtemp, readFile, stat, writeFile} from 'fs/promises'; +import {mkdtemp, readFile, writeFile} from 'fs/promises'; import os from 'os'; import path from 'path'; import {TLSSocket} from 'tls'; import {Protocol} from 'devtools-protocol'; import expect from 'expect'; -import {BrowserFetcher, TimeoutError} from 'puppeteer'; +import {TimeoutError} from 'puppeteer'; import {Page} from 'puppeteer-core/internal/api/Page.js'; import {rmSync} from 'puppeteer-core/internal/node/util/fs.js'; import sinon from 'sinon'; @@ -38,93 +38,6 @@ describe('Launcher specs', function () { } describe('Puppeteer', function () { - describe('BrowserFetcher', function () { - it('should download and extract chrome linux binary', async () => { - const {server} = getTestState(); - - const downloadsFolder = await mkdtemp(TMP_FOLDER); - const browserFetcher = new BrowserFetcher({ - platform: 'linux', - path: downloadsFolder, - host: server.PREFIX, - }); - const expectedRevision = '123456'; - let revisionInfo = browserFetcher.revisionInfo(expectedRevision); - server.setRoute( - revisionInfo.url.substring(server.PREFIX.length), - (req, res) => { - server.serveFile(req, res, '/chromium-linux.zip'); - } - ); - - expect(revisionInfo.local).toBe(false); - expect(browserFetcher.platform()).toBe('linux'); - expect(browserFetcher.product()).toBe('chrome'); - expect(!!browserFetcher.host()).toBe(true); - expect(await browserFetcher.canDownload('100000')).toBe(false); - expect(await browserFetcher.canDownload(expectedRevision)).toBe(true); - - revisionInfo = (await browserFetcher.download(expectedRevision))!; - expect(revisionInfo.local).toBe(true); - expect(await readFile(revisionInfo.executablePath, 'utf8')).toBe( - 'LINUX BINARY\n' - ); - const expectedPermissions = os.platform() === 'win32' ? 0o666 : 0o755; - expect((await stat(revisionInfo.executablePath)).mode & 0o777).toBe( - expectedPermissions - ); - expect(browserFetcher.localRevisions()).toEqual([expectedRevision]); - await browserFetcher.remove(expectedRevision); - expect(browserFetcher.localRevisions()).toEqual([]); - rmSync(downloadsFolder); - }); - it('should download and extract firefox linux binary', async () => { - const {server} = getTestState(); - - const downloadsFolder = await mkdtemp(TMP_FOLDER); - const browserFetcher = new BrowserFetcher({ - platform: 'linux', - path: downloadsFolder, - host: server.PREFIX, - product: 'firefox', - }); - const expectedVersion = '75.0a1'; - let revisionInfo = browserFetcher.revisionInfo(expectedVersion); - server.setRoute( - revisionInfo.url.substring(server.PREFIX.length), - (req, res) => { - server.serveFile( - req, - res, - `/firefox-${expectedVersion}.en-US.linux-x86_64.tar.bz2` - ); - } - ); - - expect(revisionInfo.local).toBe(false); - expect(browserFetcher.platform()).toBe('linux'); - expect(browserFetcher.product()).toBe('firefox'); - expect(await browserFetcher.canDownload('100000')).toBe(false); - expect(await browserFetcher.canDownload(expectedVersion)).toBe(true); - - revisionInfo = (await browserFetcher.download(expectedVersion))!; - expect(revisionInfo.local).toBe(true); - expect(await readFile(revisionInfo.executablePath, 'utf8')).toBe( - 'FIREFOX LINUX BINARY\n' - ); - const expectedPermissions = os.platform() === 'win32' ? 0o666 : 0o755; - expect((await stat(revisionInfo.executablePath)).mode & 0o777).toBe( - expectedPermissions - ); - expect(await browserFetcher.localRevisions()).toEqual([ - expectedVersion, - ]); - await browserFetcher.remove(expectedVersion); - expect(await browserFetcher.localRevisions()).toEqual([]); - rmSync(downloadsFolder); - }); - }); - describe('Browser.disconnect', function () { it('should reject navigation when browser closes', async () => { const {server, puppeteer, defaultBrowserOptions} = getTestState(); @@ -910,68 +823,6 @@ describe('Launcher specs', function () { } }); }); - - describe('when the product is chrome, platform is not darwin, and arch is arm64', () => { - describe('and the executable exists', () => { - it('returns /usr/bin/chromium-browser', async () => { - const {puppeteer} = getTestState(); - const osPlatformStub = sinon.stub(os, 'platform').returns('linux'); - const osArchStub = sinon.stub(os, 'arch').returns('arm64'); - const fsExistsStub = sinon.stub(fs, 'existsSync'); - fsExistsStub.withArgs('/usr/bin/chromium-browser').returns(true); - - const executablePath = puppeteer.executablePath(); - - expect(executablePath).toEqual('/usr/bin/chromium-browser'); - - osPlatformStub.restore(); - osArchStub.restore(); - fsExistsStub.restore(); - }); - describe('and the executable path is configured', () => { - const sandbox = sinon.createSandbox(); - - beforeEach(() => { - const {puppeteer} = getTestState(); - sandbox - .stub(puppeteer.configuration, 'executablePath') - .value('SOME_CUSTOM_EXECUTABLE'); - }); - - afterEach(() => { - sandbox.restore(); - }); - - it('its value is used', async () => { - const {puppeteer} = getTestState(); - try { - puppeteer.executablePath(); - } catch (error) { - expect((error as Error).message).toContain( - 'SOME_CUSTOM_EXECUTABLE' - ); - } - }); - }); - }); - describe('and the executable does not exist', () => { - it('does not return /usr/bin/chromium-browser', async () => { - const {puppeteer} = getTestState(); - const osPlatformStub = sinon.stub(os, 'platform').returns('linux'); - const osArchStub = sinon.stub(os, 'arch').returns('arm64'); - const fsExistsStub = sinon.stub(fs, 'existsSync'); - fsExistsStub.withArgs('/usr/bin/chromium-browser').returns(false); - - expect(() => { - return puppeteer.executablePath(); - }).toThrowError(); - - osPlatformStub.restore(); - osArchStub.restore(); - fsExistsStub.restore(); - }); - }); - }); }); }); diff --git a/test/src/mocha-utils.ts b/test/src/mocha-utils.ts index 83468569c71..70d9ab505e5 100644 --- a/test/src/mocha-utils.ts +++ b/test/src/mocha-utils.ts @@ -120,11 +120,7 @@ const defaultBrowserOptions = Object.assign( })(); const setupGoldenAssertions = (): void => { - let suffix = product.toLowerCase(); - if (suffix === 'chrome') { - // TODO: to avoid moving golden folders. - suffix = 'chromium'; - } + const suffix = product.toLowerCase(); const GOLDEN_DIR = path.join(__dirname, `../golden-${suffix}`); const OUTPUT_DIR = path.join(__dirname, `../output-${suffix}`); if (fs.existsSync(OUTPUT_DIR)) { diff --git a/test/src/navigation.spec.ts b/test/src/navigation.spec.ts index 00b2e07145a..0f2c17e36f7 100644 --- a/test/src/navigation.spec.ts +++ b/test/src/navigation.spec.ts @@ -759,7 +759,7 @@ describe('navigation', function () { it('should return matching responses', async () => { const {page, server} = getTestState(); - // Disable cache: otherwise, chromium will cache similar requests. + // Disable cache: otherwise, the browser will cache similar requests. await page.setCacheEnabled(false); await page.goto(server.EMPTY_PAGE); // Attach three frames. diff --git a/tools/bisect.ts b/tools/bisect.ts deleted file mode 100755 index 5787df3954b..00000000000 --- a/tools/bisect.ts +++ /dev/null @@ -1,319 +0,0 @@ -#!/usr/bin/env node -/** - * Copyright 2018 Google Inc. All rights reserved. - * - * 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. - */ - -import {execSync, fork, spawn} from 'child_process'; -import fs from 'fs'; -import path from 'path'; -import URL from 'url'; - -import debug from 'debug'; -import minimist from 'minimist'; -import ProgressBar from 'progress'; -import {BrowserFetcher, BrowserFetcherRevisionInfo} from 'puppeteer'; - -const COLOR_RESET = '\x1b[0m'; -const COLOR_RED = '\x1b[31m'; -const COLOR_GREEN = '\x1b[32m'; -const COLOR_YELLOW = '\x1b[33m'; - -const argv = minimist(process.argv.slice(2), {}); - -const help = ` -Usage: - node bisect.js --good --bad