Skip to content

Commit

Permalink
upgrade puppeteer version
Browse files Browse the repository at this point in the history
  • Loading branch information
vpalmisano committed Jun 12, 2024
1 parent 0851a63 commit ee33645
Show file tree
Hide file tree
Showing 7 changed files with 520 additions and 411 deletions.
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ ENV CHROMIUM_PATH=/usr/bin/chromium-browser-unstable
ENTRYPOINT ["/app/entrypoint.sh"]

COPY package.json yarn.lock /app/
RUN PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=true yarn --production=true
RUN PUPPETEER_SKIP_DOWNLOAD=true yarn --production=true

COPY scripts /app/scripts/
COPY app.min.js entrypoint.sh /app/
23 changes: 11 additions & 12 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
"webrtcperf": "app.min.js"
},
"engines": {
"node": ">=16.0.0"
"node": ">=18.0.0"
},
"scripts": {
"prepare": "yarn lint && tsc -b && webpack",
Expand All @@ -48,7 +48,8 @@
},
"license": "AGPL-3.0-or-later",
"dependencies": {
"axios": "^1.6.8",
"@puppeteer/browsers": "^2.2.3",
"axios": "^1.7.2",
"browserify": "^17.0.0",
"camel-case": "^4.1.2",
"chalk": "^4.1.2",
Expand All @@ -73,27 +74,26 @@
"pidtree": "^0.6.0",
"pidusage": "^3.0.2",
"prom-client": "^15.1.2",
"puppeteer": "^19.11.1",
"puppeteer-core": "^19.11.1",
"puppeteer-extra-plugin-stealth": "^2.11.2",
"puppeteer": "^22.10.1",
"puppeteer-core": "^22.10.1",
"puppeteer-intercept-and-modify-requests": "^1.3.1",
"sdp-transform": "^2.14.2",
"sprintf-js": "^1.1.3",
"tar-fs": "^2.1.1",
"terser": "^5.31.0",
"terser": "^5.31.1",
"tesseract.js": "^5.1.0",
"uuid": "^9.0.1",
"word-wrap": "^1.2.5",
"ws": "^8.17.0",
"yaml": "^2.4.2"
"yaml": "^2.4.5"
},
"devDependencies": {
"@types/browserify": "^12.0.40",
"@types/compression": "^1.7.5",
"@types/convict": "^6.1.6",
"@types/convict-format-with-validator": "^6.0.5",
"@types/fast-stats": "^0.0.35",
"@types/node": "^20.12.12",
"@types/node": "^20.14.2",
"@types/node-fetch": "^2.6.11",
"@types/node-os-utils": "^1.3.4",
"@types/pem": "^1.14.4",
Expand All @@ -114,18 +114,17 @@
"eslint-plugin-jest": "^27.9.0",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-prettier": "^5.1.3",
"eslint-plugin-promise": "^6.1.1",
"eslint-plugin-promise": "^6.2.0",
"eslint-plugin-simple-import-sort": "^10.0.0",
"eslint-plugin-unused-imports": "^2.0.0",
"nexe": "^4.0.0-rc.6",
"nodemon": "^2.0.22",
"prettier": "^3.2.5",
"prettier": "^3.3.2",
"terser-webpack-plugin": "^5.3.10",
"ts-loader": "^9.5.1",
"ts-node": "^10.9.2",
"typedoc": "^0.25.13",
"typescript": "^5.4.5",
"webpack": "^5.91.0",
"webpack": "^5.92.0",
"webpack-cli": "^5.1.4",
"webpack-node-externals": "^3.0.0",
"yarn-upgrade-minor": "^1.0.13"
Expand Down
6 changes: 3 additions & 3 deletions src/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import {
stopThrottle,
} from './throttle'
import {
checkChromiumExecutable,
checkChromeExecutable,
logger,
registerExitHandler,
resolvePackagePath,
Expand Down Expand Up @@ -79,9 +79,9 @@ export async function setupApplication(
await startThrottle(config.throttleConfig)
}

// Download chromium if necessary.
// Download browser if necessary.
if (!config.chromiumUrl && !config.chromiumPath) {
await checkChromiumExecutable()
await checkChromeExecutable()
}

// Start session function.
Expand Down
8 changes: 4 additions & 4 deletions src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -209,14 +209,14 @@ to be included into the random selection.`,
env: 'CHROMIUM_PATH',
arg: 'chromium-path',
},
chromiumRevision: {
doc: `The Chromium revision number. It will be downloaded if the chromium \
chromiumVersion: {
doc: `The Chromium version. It will be downloaded if the chromium \
path is not provided.`,
format: String,
nullable: false,
default: puppeteer.default.browserRevision,
env: 'CHROMIUM_REVISION',
arg: 'chromium-revision',
env: 'CHROMIUM_VERSION',
arg: 'chromium-version',
},
chromiumUrl: {
doc: `The remote Chromium URL (\`http://HOST:PORT\`).
Expand Down
10 changes: 5 additions & 5 deletions src/session.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import { gunzipSync } from 'zlib'
import { rtcStatKey, RtcStats, updateRtcStats } from './rtcstats'
import { getSessionThrottleValues } from './throttle'
import {
checkChromiumExecutable,
checkChromeExecutable,
downloadUrl,
getProcessStats,
getSystemStats,
Expand Down Expand Up @@ -631,7 +631,7 @@ export class Session extends EventEmitter {
// run a browser instance locally
let executablePath = this.chromiumPath
if (!executablePath || !fs.existsSync(executablePath)) {
executablePath = await checkChromiumExecutable()
executablePath = await checkChromeExecutable()
log.debug(`using executablePath=${executablePath}`)
}

Expand Down Expand Up @@ -685,7 +685,7 @@ exec sg ${group} -c /tmp/webrtcperf-launcher-${mark}-browser`,
try {
// log.debug('defaultArgs:', puppeteer.defaultArgs());
this.browser = await puppeteer.launch({
headless: this.display ? false : 'new',
headless: this.display ? false : true,
executablePath,
handleSIGINT: false,
env,
Expand Down Expand Up @@ -822,7 +822,7 @@ exec sg ${group} -c /tmp/webrtcperf-launcher-${mark}-browser`,
)

if (this.incognito) {
this.context = await this.browser.createIncognitoBrowserContext()
this.context = await this.browser.createBrowserContext()
} else {
this.context = this.browser.defaultBrowserContext()
}
Expand Down Expand Up @@ -1779,7 +1779,7 @@ window.SERVER_USE_HTTPS = ${this.serverUseHttps};
if (this.chromiumUrl) {
log.debug(`${this.id} disconnect from browser`)
try {
this.browser.disconnect()
await this.browser.disconnect()
} catch (err) {
log.warn(`browser disconnect error: ${(err as Error).message}`)
}
Expand Down
117 changes: 101 additions & 16 deletions src/utils.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
import {
Browser,
computeExecutablePath,
getInstalledBrowsers,
getVersionComparator,
install,
} from '@puppeteer/browsers'
import axios from 'axios'
import { spawn } from 'child_process'
import { createHash } from 'crypto'
Expand All @@ -13,7 +20,7 @@ import os, { networkInterfaces } from 'os'
import path, { dirname } from 'path'
import pidtree from 'pidtree'
import pidusage from 'pidusage'
import { BrowserFetcher, Page } from 'puppeteer-core'
import puppeteer, { Page } from 'puppeteer-core'

import { Session } from './session'

Expand Down Expand Up @@ -604,34 +611,43 @@ SIGNALS.forEach(event =>

/**
* Downloads the configured chrome executable if it doesn't exists into the
* `$HOME/.webrtcperf/chromium` directory.
* `$HOME/.webrtcperf/chrome` directory.
* @returns The revision info.
*/
export async function checkChromiumExecutable(): Promise<string> {
export async function checkChromeExecutable(): Promise<string> {
// eslint-disable-next-line @typescript-eslint/no-var-requires
const { loadConfig } = require('./config')
const config = loadConfig()
const cacheDir = path.join(os.homedir(), '.webrtcperf/chromium')
const browserFetcher = new BrowserFetcher({ path: cacheDir })
const revisions = await browserFetcher.localRevisions()
revisions.sort((a: string, b: string) => b.localeCompare(a))
log.debug(`Available chromium revisions: ${revisions}`)
if (revisions.indexOf(config.chromiumRevision) === -1) {
log.info(`Downloading chromium revision ${config.chromiumRevision}...`)
const cacheDir = path.join(os.homedir(), '.webrtcperf/chrome')

const browsers = await getInstalledBrowsers({ cacheDir })
const revisions = browsers.map(b => b.buildId)
const browser = Browser.CHROME
revisions.sort(getVersionComparator(browser))
log.debug(`Available chrome versions: ${revisions}`)
const requiredRevision = config.chromiumVersion
if (revisions.indexOf(requiredRevision) === -1) {
log.info(`Downloading chrome ${requiredRevision}...`)
let progress = 0
await browserFetcher.download(
config.chromiumRevision,
(downloadedBytes: number, totalBytes: number) => {
await install({
browser,
buildId: requiredRevision,
cacheDir,
downloadProgressCallback: (downloadedBytes, totalBytes) => {
const cur = Math.round((100 * downloadedBytes) / totalBytes)
if (cur - progress > 1) {
progress = cur
log.info(` ${progress}%`)
}
},
)
log.info(`Downloading chromium revision ${config.chromiumRevision} done.`)
})
log.info(`Downloading chrome ${requiredRevision} done.`)
}
return browserFetcher.revisionInfo(config.chromiumRevision).executablePath
return computeExecutablePath({
browser,
cacheDir,
buildId: requiredRevision,
})
}

export function clampMinMax(value: number, min: number, max: number): number {
Expand Down Expand Up @@ -1059,3 +1075,72 @@ export async function portForwarder(port: number, listenInterface?: string) {
controller.abort()
}
}

export async function pageScreenshot(
url: string,
filePath: string,
width = 1920,
height = 1024,
selector = 'body',
headers?: Record<string, string>,
extraCss?: string,
): Promise<void> {
log.debug(`pageScreenshot ${url} -> ${filePath}`)
await fs.promises.mkdir(path.dirname(filePath), { recursive: true })
let executablePath = process.env.CHROMIUM_PATH
if (!executablePath || !fs.existsSync(executablePath)) {
executablePath = await checkChromeExecutable()
}
const browser = await puppeteer.launch({
headless: true,
ignoreHTTPSErrors: true,
executablePath,
defaultViewport: {
width,
height,
deviceScaleFactor: 1,
isMobile: false,
hasTouch: false,
isLandscape: false,
},
args: [
'--no-sandbox',
'--disable-setuid-sandbox',
//'--remote-debugging-port=9222',
],
})
const page = await browser.newPage()
if (headers) {
await page.setExtraHTTPHeaders(headers)
}
if (extraCss) {
await page.evaluateOnNewDocument((css: string) => {
document.addEventListener('DOMContentLoaded', () => {
const style = document.createElement('style')
style.setAttribute('id', 'webrtcperf-extra-style')
style.setAttribute('type', 'text/css')
style.innerHTML = css
document.head.appendChild(style)
})
}, extraCss)
}
await page.goto(url, {
waitUntil: ['domcontentloaded', 'networkidle0'],
timeout: 60 * 1000,
})
try {
const element = await page.waitForSelector(selector, {
visible: true,
timeout: 15 * 1000,
})
if (!element) {
throw new Error(`pageScreenshot selector "${selector}" not found`)
}
await element.screenshot({ path: filePath })
} catch (err) {
log.error(`pageScreenshot error: ${(err as Error).message}`)
} finally {
await page.close()
await browser.close()
}
}
Loading

0 comments on commit ee33645

Please sign in to comment.