mirror of
https://github.com/microsoft/playwright.git
synced 2024-12-14 21:53:35 +03:00
chore: move extracting of browser out-of-process (#23739)
https://github.com/microsoft/playwright/issues/23729
This commit is contained in:
parent
de422b5afb
commit
b44723708c
@ -19,15 +19,14 @@ import fs from 'fs';
|
||||
import os from 'os';
|
||||
import path from 'path';
|
||||
import childProcess from 'child_process';
|
||||
import { getUserAgent } from '../../utils/userAgent';
|
||||
import { existsAsync } from '../../utils/fileUtils';
|
||||
import { debugLogger } from '../../common/debugLogger';
|
||||
import { extract } from '../../zipBundle';
|
||||
import { ManualPromise } from '../../utils/manualPromise';
|
||||
import { colors } from '../../utilsBundle';
|
||||
import { browserDirectoryToMarkerFilePath } from '.';
|
||||
|
||||
export async function downloadBrowserWithProgressBar(title: string, browserDirectory: string, executablePath: string | undefined, downloadURLs: string[], downloadFileName: string, downloadConnectionTimeout: number): Promise<boolean> {
|
||||
if (await existsAsync(browserDirectory)) {
|
||||
if (await existsAsync(browserDirectoryToMarkerFilePath(browserDirectory))) {
|
||||
// Already downloaded.
|
||||
debugLogger.log('install', `${title} is already downloaded.`);
|
||||
return false;
|
||||
@ -40,24 +39,20 @@ export async function downloadBrowserWithProgressBar(title: string, browserDirec
|
||||
debugLogger.log('install', `downloading ${title} - attempt #${attempt}`);
|
||||
const url = downloadURLs[(attempt - 1) % downloadURLs.length];
|
||||
logPolitely(`Downloading ${title}` + colors.dim(` from ${url}`));
|
||||
const { error } = await downloadFileOutOfProcess(url, zipPath, getUserAgent(), downloadConnectionTimeout);
|
||||
const { error } = await downloadBrowserWithProgressBarOutOfProcess(title, browserDirectory, url, zipPath, executablePath, downloadConnectionTimeout);
|
||||
if (!error) {
|
||||
debugLogger.log('install', `SUCCESS downloading ${title}`);
|
||||
debugLogger.log('install', `SUCCESS installing ${title}`);
|
||||
break;
|
||||
}
|
||||
if (await existsAsync(zipPath))
|
||||
await fs.promises.unlink(zipPath);
|
||||
if (await existsAsync(browserDirectory))
|
||||
await fs.promises.rmdir(browserDirectory, { recursive: true });
|
||||
const errorMessage = error?.message || '';
|
||||
debugLogger.log('install', `attempt #${attempt} - ERROR: ${errorMessage}`);
|
||||
if (attempt >= retryCount)
|
||||
throw error;
|
||||
}
|
||||
debugLogger.log('install', `extracting archive`);
|
||||
debugLogger.log('install', `-- zip: ${zipPath}`);
|
||||
debugLogger.log('install', `-- location: ${browserDirectory}`);
|
||||
await extract(zipPath, { dir: browserDirectory });
|
||||
if (executablePath) {
|
||||
debugLogger.log('install', `fixing permissions at ${executablePath}`);
|
||||
await fs.promises.chmod(executablePath, 0o755);
|
||||
}
|
||||
} catch (e) {
|
||||
debugLogger.log('install', `FAILED installation ${title} with error: ${e}`);
|
||||
process.exitCode = 1;
|
||||
@ -75,8 +70,8 @@ export async function downloadBrowserWithProgressBar(title: string, browserDirec
|
||||
* Thats why we execute it in a separate process and check manually if the destination file exists.
|
||||
* https://github.com/microsoft/playwright/issues/17394
|
||||
*/
|
||||
function downloadFileOutOfProcess(url: string, destinationPath: string, userAgent: string, downloadConnectionTimeout: number): Promise<{ error: Error | null }> {
|
||||
const cp = childProcess.fork(path.join(__dirname, 'oopDownloadMain.js'), [url, destinationPath, userAgent, String(downloadConnectionTimeout)]);
|
||||
function downloadBrowserWithProgressBarOutOfProcess(title: string, browserDirectory: string, url: string, zipPath: string, executablePath: string | undefined, downloadConnectionTimeout: number): Promise<{ error: Error | null }> {
|
||||
const cp = childProcess.fork(path.join(__dirname, 'oopDownloadBrowserMain.js'), [title, browserDirectory, url, zipPath, executablePath || '', String(downloadConnectionTimeout)]);
|
||||
const promise = new ManualPromise<{ error: Error | null }>();
|
||||
cp.on('message', (message: any) => {
|
||||
if (message?.method === 'log')
|
||||
@ -87,8 +82,8 @@ function downloadFileOutOfProcess(url: string, destinationPath: string, userAgen
|
||||
promise.resolve({ error: new Error(`Download failure, code=${code}`) });
|
||||
return;
|
||||
}
|
||||
if (!fs.existsSync(destinationPath))
|
||||
promise.resolve({ error: new Error(`Download failure, ${destinationPath} does not exist`) });
|
||||
if (!fs.existsSync(browserDirectoryToMarkerFilePath(browserDirectory)))
|
||||
promise.resolve({ error: new Error(`Download failure, ${browserDirectoryToMarkerFilePath(browserDirectory)} does not exist`) });
|
||||
else
|
||||
promise.resolve({ error: null });
|
||||
});
|
||||
|
@ -839,7 +839,6 @@ export class Registry {
|
||||
await downloadBrowserWithProgressBar(title, descriptor.dir, executablePath, downloadURLs, downloadFileName, downloadConnectionTimeout).catch(e => {
|
||||
throw new Error(`Failed to download ${title}, caused by\n${e.stack}`);
|
||||
});
|
||||
await fs.promises.writeFile(markerFilePath(descriptor.dir), '');
|
||||
}
|
||||
|
||||
private async _installMSEdgeChannel(channel: 'msedge'|'msedge-beta'|'msedge-dev', scripts: Record<'linux' | 'darwin' | 'win32', string>) {
|
||||
@ -920,7 +919,7 @@ export class Registry {
|
||||
(browserName === 'webkit' && browserRevision >= 1307) ||
|
||||
// All new applications have a marker file right away.
|
||||
(browserName !== 'firefox' && browserName !== 'chromium' && browserName !== 'webkit');
|
||||
if (!shouldHaveMarkerFile || (await existsAsync(markerFilePath(usedBrowserPath))))
|
||||
if (!shouldHaveMarkerFile || (await existsAsync(browserDirectoryToMarkerFilePath(usedBrowserPath))))
|
||||
usedBrowserPaths.add(usedBrowserPath);
|
||||
}
|
||||
} catch (e) {
|
||||
@ -942,7 +941,7 @@ export class Registry {
|
||||
}
|
||||
}
|
||||
|
||||
function markerFilePath(browserDirectory: string): string {
|
||||
export function browserDirectoryToMarkerFilePath(browserDirectory: string): string {
|
||||
return path.join(browserDirectory, 'INSTALLATION_COMPLETE');
|
||||
}
|
||||
|
||||
|
@ -18,6 +18,9 @@ import fs from 'fs';
|
||||
import { progress as ProgressBar } from '../../utilsBundle';
|
||||
import { httpRequest } from '../../utils/network';
|
||||
import { ManualPromise } from '../../utils/manualPromise';
|
||||
import { extract } from '../../zipBundle';
|
||||
import { getUserAgent } from '../../utils/userAgent';
|
||||
import { browserDirectoryToMarkerFilePath } from '.';
|
||||
|
||||
type OnProgressCallback = (downloadedBytes: number, totalBytes: number) => void;
|
||||
type DownloadFileLogger = (message: string) => void;
|
||||
@ -140,13 +143,24 @@ function toMegabytes(bytes: number) {
|
||||
}
|
||||
|
||||
async function main() {
|
||||
const [url, destination, userAgent, downloadConnectionTimeout] = process.argv.slice(2);
|
||||
await downloadFile(url, destination, {
|
||||
const log = (message: string) => process.send?.({ method: 'log', params: { message } });
|
||||
const [title, browserDirectory, url, zipPath, executablePath, downloadConnectionTimeout] = process.argv.slice(2);
|
||||
await downloadFile(url, zipPath, {
|
||||
progressCallback: getDownloadProgress(),
|
||||
userAgent,
|
||||
log: message => process.send?.({ method: 'log', params: { message } }),
|
||||
userAgent: getUserAgent(),
|
||||
log,
|
||||
connectionTimeout: +downloadConnectionTimeout,
|
||||
});
|
||||
log(`SUCCESS downloading ${title}`);
|
||||
log(`extracting archive`);
|
||||
log(`-- zip: ${zipPath}`);
|
||||
log(`-- location: ${browserDirectory}`);
|
||||
await extract(zipPath, { dir: browserDirectory });
|
||||
if (executablePath) {
|
||||
log(`fixing permissions at ${executablePath}`);
|
||||
await fs.promises.chmod(executablePath, 0o755);
|
||||
}
|
||||
await fs.promises.writeFile(browserDirectoryToMarkerFilePath(browserDirectory), '');
|
||||
}
|
||||
|
||||
main().catch(error => {
|
Loading…
Reference in New Issue
Block a user