diff --git a/docs/api.md b/docs/api.md index 65c6014773caf..e4109a15dbff4 100644 --- a/docs/api.md +++ b/docs/api.md @@ -457,6 +457,7 @@ const puppeteer = require('puppeteer'); - `isLandscape` <[boolean]> Specifies if viewport is in landscape mode. Defaults to `false`. - `slowMo` <[number]> Slows down Puppeteer operations by the specified amount of milliseconds. Useful so that you can see what is going on. - `transport` <[ConnectionTransport]> **Experimental** Specify a custom transport object for Puppeteer to use. + - `product` <[string]> Possible values are: `chrome`, `firefox`. Defaults to `chrome`. - returns: <[Promise]<[Browser]>> This methods attaches Puppeteer to an existing browser instance. diff --git a/examples/cross-browser.js b/examples/cross-browser.js new file mode 100644 index 0000000000000..1206d90c4bede --- /dev/null +++ b/examples/cross-browser.js @@ -0,0 +1,48 @@ +const puppeteer = require('puppeteer'); + +/** + * To have Puppeteer fetch a Firefox binary for you, first run: + * + * PUPPETEER_PRODUCT=firefox npm install + * + * To get additional logging about which browser binary is executed, + * run this example as: + * + * DEBUG=puppeteer:launcher NODE_PATH=../ node examples/cross-browser.js + * + * You can set a custom binary with the `executablePath` launcher option. + * + * + */ + +const firefoxOptions = { + product: 'firefox', + extraPrefsFirefox: { + // Enable additional Firefox logging from its protocol implementation + // 'remote.log.level': 'Trace', + }, + // Make browser logs visible + dumpio: true, +}; + +(async() => { + const browser = await puppeteer.launch(firefoxOptions); + + const page = await browser.newPage(); + console.log(await browser.version()); + + await page.goto('https://news.ycombinator.com/'); + + // Extract articles from the page. + const resultsSelector = '.storylink'; + const links = await page.evaluate(resultsSelector => { + const anchors = Array.from(document.querySelectorAll(resultsSelector)); + return anchors.map(anchor => { + const title = anchor.textContent.trim(); + return `${title} - ${anchor.href}`; + }); + }, resultsSelector); + console.log(links.join('\n')); + + await browser.close(); +})(); diff --git a/src/Puppeteer.js b/src/Puppeteer.js index 7b12ae9b4f6c8..e477a05d21056 100644 --- a/src/Puppeteer.js +++ b/src/Puppeteer.js @@ -40,13 +40,29 @@ module.exports = class { } /** - * @param {!(Launcher.BrowserOptions & {browserWSEndpoint?: string, browserURL?: string, transport?: !Puppeteer.ConnectionTransport})} options + * @param {!(Launcher.BrowserOptions & {browserWSEndpoint?: string, browserURL?: string, transport?: !Puppeteer.ConnectionTransport}) & {product?: string}=} options * @return {!Promise} */ connect(options) { + this._productName = options.product; return this._launcher.connect(options); } + /** + * @param {string} name + */ + set _productName(name) { + this._changedProduct = this.__productName !== name; + this.__productName = name; + } + + /** + * @return {string} + */ + get _productName() { + return this.__productName; + } + /** * @return {string} */ @@ -58,7 +74,7 @@ module.exports = class { * @return {!Puppeteer.ProductLauncher} */ get _launcher() { - if (!this._lazyLauncher || this._lazyLauncher.product !== this._productName) { + if (!this._lazyLauncher || this._lazyLauncher.product !== this._productName || this._changedProduct) { // @ts-ignore const packageJson = require('../package.json'); switch (this._productName) { @@ -69,6 +85,7 @@ module.exports = class { default: this._preferredRevision = packageJson.puppeteer.chromium_revision; } + this._changedProduct = false; this._lazyLauncher = Launcher(this._projectRoot, this._preferredRevision, this._isPuppeteerCore, this._productName); } return this._lazyLauncher;