Best JavaScript code snippet using playwright-internal
index.js
Source:index.js  
1"use strict";2Object.defineProperty(exports, "__esModule", {3  value: true4});5exports.Registry = void 0;6exports.buildPlaywrightCLICommand = buildPlaywrightCLICommand;7exports.findChromiumChannel = findChromiumChannel;8exports.installBrowsersForNpmInstall = installBrowsersForNpmInstall;9exports.installDefaultBrowsersForNpmInstall = installDefaultBrowsersForNpmInstall;10exports.registryDirectory = exports.registry = void 0;11Object.defineProperty(exports, "writeDockerVersion", {12  enumerable: true,13  get: function () {14    return _dependencies.writeDockerVersion;15  }16});17var os = _interopRequireWildcard(require("os"));18var _path = _interopRequireDefault(require("path"));19var util = _interopRequireWildcard(require("util"));20var fs = _interopRequireWildcard(require("fs"));21var _properLockfile = _interopRequireDefault(require("proper-lockfile"));22var _ubuntuVersion = require("../../utils/ubuntuVersion");23var _netUtils = require("../../common/netUtils");24var _userAgent = require("../../common/userAgent");25var _utils = require("../../utils");26var _fileUtils = require("../../utils/fileUtils");27var _hostPlatform = require("../../utils/hostPlatform");28var _spawnAsync = require("../../utils/spawnAsync");29var _dependencies = require("./dependencies");30var _browserFetcher = require("./browserFetcher");31function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }32function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }33function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }34/**35 * Copyright 2017 Google Inc. All rights reserved.36 * Modifications copyright (c) Microsoft Corporation.37 *38 * Licensed under the Apache License, Version 2.0 (the "License");39 * you may not use this file except in compliance with the License.40 * You may obtain a copy of the License at41 *42 *     http://www.apache.org/licenses/LICENSE-2.043 *44 * Unless required by applicable law or agreed to in writing, software45 * distributed under the License is distributed on an "AS IS" BASIS,46 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.47 * See the License for the specific language governing permissions and48 * limitations under the License.49 */50const PACKAGE_PATH = _path.default.join(__dirname, '..', '..', '..');51const BIN_PATH = _path.default.join(__dirname, '..', '..', '..', 'bin');52const EXECUTABLE_PATHS = {53  'chromium': {54    'linux': ['chrome-linux', 'chrome'],55    'mac': ['chrome-mac', 'Chromium.app', 'Contents', 'MacOS', 'Chromium'],56    'win': ['chrome-win', 'chrome.exe']57  },58  'firefox': {59    'linux': ['firefox', 'firefox'],60    'mac': ['firefox', 'Nightly.app', 'Contents', 'MacOS', 'firefox'],61    'win': ['firefox', 'firefox.exe']62  },63  'webkit': {64    'linux': ['pw_run.sh'],65    'mac': ['pw_run.sh'],66    'win': ['Playwright.exe']67  },68  'ffmpeg': {69    'linux': ['ffmpeg-linux'],70    'mac': ['ffmpeg-mac'],71    'win': ['ffmpeg-win64.exe']72  }73};74const DOWNLOAD_PATHS = {75  'chromium': {76    '<unknown>': undefined,77    'generic-linux': 'builds/chromium/%s/chromium-linux.zip',78    'generic-linux-arm64': 'builds/chromium/%s/chromium-linux-arm64.zip',79    'ubuntu18.04': 'builds/chromium/%s/chromium-linux.zip',80    'ubuntu20.04': 'builds/chromium/%s/chromium-linux.zip',81    'ubuntu18.04-arm64': 'builds/chromium/%s/chromium-linux-arm64.zip',82    'ubuntu20.04-arm64': 'builds/chromium/%s/chromium-linux-arm64.zip',83    'mac10.13': 'builds/chromium/%s/chromium-mac.zip',84    'mac10.14': 'builds/chromium/%s/chromium-mac.zip',85    'mac10.15': 'builds/chromium/%s/chromium-mac.zip',86    'mac11': 'builds/chromium/%s/chromium-mac.zip',87    'mac11-arm64': 'builds/chromium/%s/chromium-mac-arm64.zip',88    'mac12': 'builds/chromium/%s/chromium-mac.zip',89    'mac12-arm64': 'builds/chromium/%s/chromium-mac-arm64.zip',90    'win64': 'builds/chromium/%s/chromium-win64.zip'91  },92  'chromium-with-symbols': {93    '<unknown>': undefined,94    'generic-linux': 'builds/chromium/%s/chromium-with-symbols-linux.zip',95    'generic-linux-arm64': 'builds/chromium/%s/chromium-with-symbols-linux-arm64.zip',96    'ubuntu18.04': 'builds/chromium/%s/chromium-with-symbols-linux.zip',97    'ubuntu20.04': 'builds/chromium/%s/chromium-with-symbols-linux.zip',98    'ubuntu18.04-arm64': 'builds/chromium/%s/chromium-with-symbols-linux-arm64.zip',99    'ubuntu20.04-arm64': 'builds/chromium/%s/chromium-with-symbols-linux-arm64.zip',100    'mac10.13': 'builds/chromium/%s/chromium-with-symbols-mac.zip',101    'mac10.14': 'builds/chromium/%s/chromium-with-symbols-mac.zip',102    'mac10.15': 'builds/chromium/%s/chromium-with-symbols-mac.zip',103    'mac11': 'builds/chromium/%s/chromium-with-symbols-mac.zip',104    'mac11-arm64': 'builds/chromium/%s/chromium-with-symbols-mac-arm64.zip',105    'mac12': 'builds/chromium/%s/chromium-with-symbols-mac.zip',106    'mac12-arm64': 'builds/chromium/%s/chromium-with-symbols-mac-arm64.zip',107    'win64': 'builds/chromium/%s/chromium-with-symbols-win64.zip'108  },109  'firefox': {110    '<unknown>': undefined,111    'generic-linux': 'builds/firefox/%s/firefox-ubuntu-20.04.zip',112    'generic-linux-arm64': 'builds/firefox/%s/firefox-ubuntu-20.04-arm64.zip',113    'ubuntu18.04': 'builds/firefox/%s/firefox-ubuntu-18.04.zip',114    'ubuntu20.04': 'builds/firefox/%s/firefox-ubuntu-20.04.zip',115    'ubuntu18.04-arm64': undefined,116    'ubuntu20.04-arm64': 'builds/firefox/%s/firefox-ubuntu-20.04-arm64.zip',117    'mac10.13': 'builds/firefox/%s/firefox-mac-11.zip',118    'mac10.14': 'builds/firefox/%s/firefox-mac-11.zip',119    'mac10.15': 'builds/firefox/%s/firefox-mac-11.zip',120    'mac11': 'builds/firefox/%s/firefox-mac-11.zip',121    'mac11-arm64': 'builds/firefox/%s/firefox-mac-11-arm64.zip',122    'mac12': 'builds/firefox/%s/firefox-mac-11.zip',123    'mac12-arm64': 'builds/firefox/%s/firefox-mac-11-arm64.zip',124    'win64': 'builds/firefox/%s/firefox-win64.zip'125  },126  'firefox-beta': {127    '<unknown>': undefined,128    'generic-linux': 'builds/firefox-beta/%s/firefox-beta-ubuntu-20.04.zip',129    'generic-linux-arm64': undefined,130    'ubuntu18.04': 'builds/firefox-beta/%s/firefox-beta-ubuntu-18.04.zip',131    'ubuntu20.04': 'builds/firefox-beta/%s/firefox-beta-ubuntu-20.04.zip',132    'ubuntu18.04-arm64': undefined,133    'ubuntu20.04-arm64': undefined,134    'mac10.13': 'builds/firefox-beta/%s/firefox-beta-mac-11.zip',135    'mac10.14': 'builds/firefox-beta/%s/firefox-beta-mac-11.zip',136    'mac10.15': 'builds/firefox-beta/%s/firefox-beta-mac-11.zip',137    'mac11': 'builds/firefox-beta/%s/firefox-beta-mac-11.zip',138    'mac11-arm64': 'builds/firefox-beta/%s/firefox-beta-mac-11-arm64.zip',139    'mac12': 'builds/firefox-beta/%s/firefox-beta-mac-11.zip',140    'mac12-arm64': 'builds/firefox-beta/%s/firefox-beta-mac-11-arm64.zip',141    'win64': 'builds/firefox-beta/%s/firefox-beta-win64.zip'142  },143  'webkit': {144    '<unknown>': undefined,145    'generic-linux': 'builds/webkit/%s/webkit-ubuntu-20.04.zip',146    'generic-linux-arm64': 'builds/webkit/%s/webkit-ubuntu-20.04-arm64.zip',147    'ubuntu18.04': 'builds/webkit/%s/webkit-ubuntu-18.04.zip',148    'ubuntu20.04': 'builds/webkit/%s/webkit-ubuntu-20.04.zip',149    'ubuntu18.04-arm64': undefined,150    'ubuntu20.04-arm64': 'builds/webkit/%s/webkit-ubuntu-20.04-arm64.zip',151    'mac10.13': undefined,152    'mac10.14': 'builds/deprecated-webkit-mac-10.14/%s/deprecated-webkit-mac-10.14.zip',153    'mac10.15': 'builds/webkit/%s/webkit-mac-10.15.zip',154    'mac11': 'builds/webkit/%s/webkit-mac-11.zip',155    'mac11-arm64': 'builds/webkit/%s/webkit-mac-11-arm64.zip',156    'mac12': 'builds/webkit/%s/webkit-mac-12.zip',157    'mac12-arm64': 'builds/webkit/%s/webkit-mac-12-arm64.zip',158    'win64': 'builds/webkit/%s/webkit-win64.zip'159  },160  'ffmpeg': {161    '<unknown>': undefined,162    'generic-linux': 'builds/ffmpeg/%s/ffmpeg-linux.zip',163    'generic-linux-arm64': 'builds/ffmpeg/%s/ffmpeg-linux-arm64.zip',164    'ubuntu18.04': 'builds/ffmpeg/%s/ffmpeg-linux.zip',165    'ubuntu20.04': 'builds/ffmpeg/%s/ffmpeg-linux.zip',166    'ubuntu18.04-arm64': 'builds/ffmpeg/%s/ffmpeg-linux-arm64.zip',167    'ubuntu20.04-arm64': 'builds/ffmpeg/%s/ffmpeg-linux-arm64.zip',168    'mac10.13': 'builds/ffmpeg/%s/ffmpeg-mac.zip',169    'mac10.14': 'builds/ffmpeg/%s/ffmpeg-mac.zip',170    'mac10.15': 'builds/ffmpeg/%s/ffmpeg-mac.zip',171    'mac11': 'builds/ffmpeg/%s/ffmpeg-mac.zip',172    'mac11-arm64': 'builds/ffmpeg/%s/ffmpeg-mac-arm64.zip',173    'mac12': 'builds/ffmpeg/%s/ffmpeg-mac.zip',174    'mac12-arm64': 'builds/ffmpeg/%s/ffmpeg-mac-arm64.zip',175    'win64': 'builds/ffmpeg/%s/ffmpeg-win64.zip'176  }177};178const registryDirectory = (() => {179  let result;180  const envDefined = (0, _utils.getFromENV)('PLAYWRIGHT_BROWSERS_PATH');181  if (envDefined === '0') {182    result = _path.default.join(__dirname, '..', '..', '..', '.local-browsers');183  } else if (envDefined) {184    result = envDefined;185  } else {186    let cacheDirectory;187    if (process.platform === 'linux') cacheDirectory = process.env.XDG_CACHE_HOME || _path.default.join(os.homedir(), '.cache');else if (process.platform === 'darwin') cacheDirectory = _path.default.join(os.homedir(), 'Library', 'Caches');else if (process.platform === 'win32') cacheDirectory = process.env.LOCALAPPDATA || _path.default.join(os.homedir(), 'AppData', 'Local');else throw new Error('Unsupported platform: ' + process.platform);188    result = _path.default.join(cacheDirectory, 'ms-playwright');189  }190  if (!_path.default.isAbsolute(result)) {191    // It is important to resolve to the absolute path:192    //   - for unzipping to work correctly;193    //   - so that registry directory matches between installation and execution.194    // INIT_CWD points to the root of `npm/yarn install` and is probably what195    // the user meant when typing the relative path.196    result = _path.default.resolve((0, _utils.getFromENV)('INIT_CWD') || process.cwd(), result);197  }198  return result;199})();200exports.registryDirectory = registryDirectory;201function isBrowserDirectory(browserDirectory) {202  const baseName = _path.default.basename(browserDirectory);203  for (const browserName of allDownloadable) {204    if (baseName.startsWith(browserName + '-')) return true;205  }206  return false;207}208function readDescriptors(browsersJSON) {209  return browsersJSON['browsers'].map(obj => {210    const name = obj.name;211    const revisionOverride = (obj.revisionOverrides || {})[_hostPlatform.hostPlatform];212    const revision = revisionOverride || obj.revision;213    const browserDirectoryPrefix = revisionOverride ? `${name}_${_hostPlatform.hostPlatform}_special` : `${name}`;214    const descriptor = {215      name,216      revision,217      installByDefault: !!obj.installByDefault,218      // Method `isBrowserDirectory` determines directory to be browser iff219      // it starts with some browser name followed by '-'. Some browser names220      // are prefixes of others, e.g. 'webkit' is a prefix of `webkit-technology-preview`.221      // To avoid older registries erroneously removing 'webkit-technology-preview', we have to222      // ensure that browser folders to never include dashes inside.223      dir: _path.default.join(registryDirectory, browserDirectoryPrefix.replace(/-/g, '_') + '-' + revision)224    };225    return descriptor;226  });227}228const allDownloadable = ['chromium', 'firefox', 'webkit', 'ffmpeg', 'firefox-beta', 'chromium-with-symbols'];229class Registry {230  constructor(browsersJSON) {231    this._executables = void 0;232    const descriptors = readDescriptors(browsersJSON);233    const findExecutablePath = (dir, name) => {234      let tokens = undefined;235      if (_hostPlatform.hostPlatform.startsWith('ubuntu') || _hostPlatform.hostPlatform.startsWith('generic-linux')) tokens = EXECUTABLE_PATHS[name]['linux'];else if (_hostPlatform.hostPlatform.startsWith('mac')) tokens = EXECUTABLE_PATHS[name]['mac'];else if (_hostPlatform.hostPlatform.startsWith('win')) tokens = EXECUTABLE_PATHS[name]['win'];236      return tokens ? _path.default.join(dir, ...tokens) : undefined;237    };238    const executablePathOrDie = (name, e, installByDefault, sdkLanguage) => {239      if (!e) throw new Error(`${name} is not supported on ${_hostPlatform.hostPlatform}`);240      const installCommand = buildPlaywrightCLICommand(sdkLanguage, `install${installByDefault ? '' : ' ' + name}`);241      if (!(0, _fileUtils.canAccessFile)(e)) {242        const prettyMessage = [`Looks like Playwright Test or Playwright was just installed or updated.`, `Please run the following command to download new browser${installByDefault ? 's' : ''}:`, ``, `    ${installCommand}`, ``, `<3 Playwright Team`].join('\n');243        throw new Error(`Executable doesn't exist at ${e}\n${(0, _utils.wrapInASCIIBox)(prettyMessage, 1)}`);244      }245      return e;246    };247    this._executables = [];248    const chromium = descriptors.find(d => d.name === 'chromium');249    const chromiumExecutable = findExecutablePath(chromium.dir, 'chromium');250    this._executables.push({251      type: 'browser',252      name: 'chromium',253      browserName: 'chromium',254      directory: chromium.dir,255      executablePath: () => chromiumExecutable,256      executablePathOrDie: sdkLanguage => executablePathOrDie('chromium', chromiumExecutable, chromium.installByDefault, sdkLanguage),257      installType: chromium.installByDefault ? 'download-by-default' : 'download-on-demand',258      validateHostRequirements: sdkLanguage => this._validateHostRequirements(sdkLanguage, 'chromium', chromium.dir, ['chrome-linux'], [], ['chrome-win']),259      _install: () => this._downloadExecutable(chromium, chromiumExecutable, DOWNLOAD_PATHS['chromium'][_hostPlatform.hostPlatform], 'PLAYWRIGHT_CHROMIUM_DOWNLOAD_HOST'),260      _dependencyGroup: 'chromium',261      _isHermeticInstallation: true262    });263    const chromiumWithSymbols = descriptors.find(d => d.name === 'chromium-with-symbols');264    const chromiumWithSymbolsExecutable = findExecutablePath(chromiumWithSymbols.dir, 'chromium');265    this._executables.push({266      type: 'tool',267      name: 'chromium-with-symbols',268      browserName: 'chromium',269      directory: chromiumWithSymbols.dir,270      executablePath: () => chromiumWithSymbolsExecutable,271      executablePathOrDie: sdkLanguage => executablePathOrDie('chromium-with-symbols', chromiumWithSymbolsExecutable, chromiumWithSymbols.installByDefault, sdkLanguage),272      installType: chromiumWithSymbols.installByDefault ? 'download-by-default' : 'download-on-demand',273      validateHostRequirements: sdkLanguage => this._validateHostRequirements(sdkLanguage, 'chromium', chromiumWithSymbols.dir, ['chrome-linux'], [], ['chrome-win']),274      _install: () => this._downloadExecutable(chromiumWithSymbols, chromiumWithSymbolsExecutable, DOWNLOAD_PATHS['chromium-with-symbols'][_hostPlatform.hostPlatform], 'PLAYWRIGHT_CHROMIUM_DOWNLOAD_HOST'),275      _dependencyGroup: 'chromium',276      _isHermeticInstallation: true277    });278    this._executables.push(this._createChromiumChannel('chrome', {279      'linux': '/opt/google/chrome/chrome',280      'darwin': '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome',281      'win32': `\\Google\\Chrome\\Application\\chrome.exe`282    }, () => this._installChromiumChannel('chrome', {283      'linux': 'reinstall_chrome_stable_linux.sh',284      'darwin': 'reinstall_chrome_stable_mac.sh',285      'win32': 'reinstall_chrome_stable_win.ps1'286    })));287    this._executables.push(this._createChromiumChannel('chrome-beta', {288      'linux': '/opt/google/chrome-beta/chrome',289      'darwin': '/Applications/Google Chrome Beta.app/Contents/MacOS/Google Chrome Beta',290      'win32': `\\Google\\Chrome Beta\\Application\\chrome.exe`291    }, () => this._installChromiumChannel('chrome-beta', {292      'linux': 'reinstall_chrome_beta_linux.sh',293      'darwin': 'reinstall_chrome_beta_mac.sh',294      'win32': 'reinstall_chrome_beta_win.ps1'295    })));296    this._executables.push(this._createChromiumChannel('chrome-dev', {297      'linux': '/opt/google/chrome-unstable/chrome',298      'darwin': '/Applications/Google Chrome Dev.app/Contents/MacOS/Google Chrome Dev',299      'win32': `\\Google\\Chrome Dev\\Application\\chrome.exe`300    }));301    this._executables.push(this._createChromiumChannel('chrome-canary', {302      'linux': '',303      'darwin': '/Applications/Google Chrome Canary.app/Contents/MacOS/Google Chrome Canary',304      'win32': `\\Google\\Chrome SxS\\Application\\chrome.exe`305    }));306    this._executables.push(this._createChromiumChannel('msedge', {307      'linux': '/opt/microsoft/msedge/msedge',308      'darwin': '/Applications/Microsoft Edge.app/Contents/MacOS/Microsoft Edge',309      'win32': `\\Microsoft\\Edge\\Application\\msedge.exe`310    }, () => this._installMSEdgeChannel('msedge', {311      'linux': 'reinstall_msedge_stable_linux.sh',312      'darwin': 'reinstall_msedge_stable_mac.sh',313      'win32': 'reinstall_msedge_stable_win.ps1'314    })));315    this._executables.push(this._createChromiumChannel('msedge-beta', {316      'linux': '/opt/microsoft/msedge-beta/msedge',317      'darwin': '/Applications/Microsoft Edge Beta.app/Contents/MacOS/Microsoft Edge Beta',318      'win32': `\\Microsoft\\Edge Beta\\Application\\msedge.exe`319    }, () => this._installMSEdgeChannel('msedge-beta', {320      'darwin': 'reinstall_msedge_beta_mac.sh',321      'linux': 'reinstall_msedge_beta_linux.sh',322      'win32': 'reinstall_msedge_beta_win.ps1'323    })));324    this._executables.push(this._createChromiumChannel('msedge-dev', {325      'linux': '/opt/microsoft/msedge-dev/msedge',326      'darwin': '/Applications/Microsoft Edge Dev.app/Contents/MacOS/Microsoft Edge Dev',327      'win32': `\\Microsoft\\Edge Dev\\Application\\msedge.exe`328    }, () => this._installMSEdgeChannel('msedge-dev', {329      'darwin': 'reinstall_msedge_dev_mac.sh',330      'linux': 'reinstall_msedge_dev_linux.sh',331      'win32': 'reinstall_msedge_dev_win.ps1'332    })));333    this._executables.push(this._createChromiumChannel('msedge-canary', {334      'linux': '',335      'darwin': '/Applications/Microsoft Edge Canary.app/Contents/MacOS/Microsoft Edge Canary',336      'win32': `\\Microsoft\\Edge SxS\\Application\\msedge.exe`337    }));338    const firefox = descriptors.find(d => d.name === 'firefox');339    const firefoxExecutable = findExecutablePath(firefox.dir, 'firefox');340    this._executables.push({341      type: 'browser',342      name: 'firefox',343      browserName: 'firefox',344      directory: firefox.dir,345      executablePath: () => firefoxExecutable,346      executablePathOrDie: sdkLanguage => executablePathOrDie('firefox', firefoxExecutable, firefox.installByDefault, sdkLanguage),347      installType: firefox.installByDefault ? 'download-by-default' : 'download-on-demand',348      validateHostRequirements: sdkLanguage => this._validateHostRequirements(sdkLanguage, 'firefox', firefox.dir, ['firefox'], [], ['firefox']),349      _install: () => this._downloadExecutable(firefox, firefoxExecutable, DOWNLOAD_PATHS['firefox'][_hostPlatform.hostPlatform], 'PLAYWRIGHT_FIREFOX_DOWNLOAD_HOST'),350      _dependencyGroup: 'firefox',351      _isHermeticInstallation: true352    });353    const firefoxBeta = descriptors.find(d => d.name === 'firefox-beta');354    const firefoxBetaExecutable = findExecutablePath(firefoxBeta.dir, 'firefox');355    this._executables.push({356      type: 'tool',357      name: 'firefox-beta',358      browserName: 'firefox',359      directory: firefoxBeta.dir,360      executablePath: () => firefoxBetaExecutable,361      executablePathOrDie: sdkLanguage => executablePathOrDie('firefox-beta', firefoxBetaExecutable, firefoxBeta.installByDefault, sdkLanguage),362      installType: firefoxBeta.installByDefault ? 'download-by-default' : 'download-on-demand',363      validateHostRequirements: sdkLanguage => this._validateHostRequirements(sdkLanguage, 'firefox', firefoxBeta.dir, ['firefox'], [], ['firefox']),364      _install: () => this._downloadExecutable(firefoxBeta, firefoxBetaExecutable, DOWNLOAD_PATHS['firefox-beta'][_hostPlatform.hostPlatform], 'PLAYWRIGHT_FIREFOX_DOWNLOAD_HOST'),365      _dependencyGroup: 'firefox',366      _isHermeticInstallation: true367    });368    const webkit = descriptors.find(d => d.name === 'webkit');369    const webkitExecutable = findExecutablePath(webkit.dir, 'webkit');370    const webkitLinuxLddDirectories = [_path.default.join('minibrowser-gtk'), _path.default.join('minibrowser-gtk', 'bin'), _path.default.join('minibrowser-gtk', 'lib'), _path.default.join('minibrowser-gtk', 'sys', 'lib'), _path.default.join('minibrowser-wpe'), _path.default.join('minibrowser-wpe', 'bin'), _path.default.join('minibrowser-wpe', 'lib'), _path.default.join('minibrowser-wpe', 'sys', 'lib')];371    this._executables.push({372      type: 'browser',373      name: 'webkit',374      browserName: 'webkit',375      directory: webkit.dir,376      executablePath: () => webkitExecutable,377      executablePathOrDie: sdkLanguage => executablePathOrDie('webkit', webkitExecutable, webkit.installByDefault, sdkLanguage),378      installType: webkit.installByDefault ? 'download-by-default' : 'download-on-demand',379      validateHostRequirements: sdkLanguage => this._validateHostRequirements(sdkLanguage, 'webkit', webkit.dir, webkitLinuxLddDirectories, ['libGLESv2.so.2', 'libx264.so'], ['']),380      _install: () => this._downloadExecutable(webkit, webkitExecutable, DOWNLOAD_PATHS['webkit'][_hostPlatform.hostPlatform], 'PLAYWRIGHT_WEBKIT_DOWNLOAD_HOST'),381      _dependencyGroup: 'webkit',382      _isHermeticInstallation: true383    });384    const ffmpeg = descriptors.find(d => d.name === 'ffmpeg');385    const ffmpegExecutable = findExecutablePath(ffmpeg.dir, 'ffmpeg');386    this._executables.push({387      type: 'tool',388      name: 'ffmpeg',389      browserName: undefined,390      directory: ffmpeg.dir,391      executablePath: () => ffmpegExecutable,392      executablePathOrDie: sdkLanguage => executablePathOrDie('ffmpeg', ffmpegExecutable, ffmpeg.installByDefault, sdkLanguage),393      installType: ffmpeg.installByDefault ? 'download-by-default' : 'download-on-demand',394      validateHostRequirements: () => Promise.resolve(),395      _install: () => this._downloadExecutable(ffmpeg, ffmpegExecutable, DOWNLOAD_PATHS['ffmpeg'][_hostPlatform.hostPlatform], 'PLAYWRIGHT_FFMPEG_DOWNLOAD_HOST'),396      _dependencyGroup: 'tools',397      _isHermeticInstallation: true398    });399  }400  _createChromiumChannel(name, lookAt, install) {401    const executablePath = (sdkLanguage, shouldThrow) => {402      const suffix = lookAt[process.platform];403      if (!suffix) {404        if (shouldThrow) throw new Error(`Chromium distribution '${name}' is not supported on ${process.platform}`);405        return undefined;406      }407      const prefixes = process.platform === 'win32' ? [process.env.LOCALAPPDATA, process.env.PROGRAMFILES, process.env['PROGRAMFILES(X86)']].filter(Boolean) : [''];408      for (const prefix of prefixes) {409        const executablePath = _path.default.join(prefix, suffix);410        if ((0, _fileUtils.canAccessFile)(executablePath)) return executablePath;411      }412      if (!shouldThrow) return undefined;413      const location = prefixes.length ? ` at ${_path.default.join(prefixes[0], suffix)}` : ``; // TODO: language-specific error message414      const installation = install ? `\nRun "${buildPlaywrightCLICommand(sdkLanguage, 'install ' + name)}"` : '';415      throw new Error(`Chromium distribution '${name}' is not found${location}${installation}`);416    };417    return {418      type: 'channel',419      name,420      browserName: 'chromium',421      directory: undefined,422      executablePath: sdkLanguage => executablePath(sdkLanguage, false),423      executablePathOrDie: sdkLanguage => executablePath(sdkLanguage, true),424      installType: install ? 'install-script' : 'none',425      validateHostRequirements: () => Promise.resolve(),426      _isHermeticInstallation: false,427      _install: install428    };429  }430  executables() {431    return this._executables;432  }433  findExecutable(name) {434    return this._executables.find(b => b.name === name);435  }436  defaultExecutables() {437    return this._executables.filter(e => e.installType === 'download-by-default');438  }439  _addRequirementsAndDedupe(executables) {440    const set = new Set();441    for (const executable of executables) {442      set.add(executable);443      if (executable.browserName === 'chromium') set.add(this.findExecutable('ffmpeg'));444    }445    return Array.from(set);446  }447  async _validateHostRequirements(sdkLanguage, browserName, browserDirectory, linuxLddDirectories, dlOpenLibraries, windowsExeAndDllDirectories) {448    if ((0, _utils.getAsBooleanFromENV)('PLAYWRIGHT_SKIP_VALIDATE_HOST_REQUIREMENTS')) {449      process.stdout.write('Skipping host requirements validation logic because `PLAYWRIGHT_SKIP_VALIDATE_HOST_REQUIREMENTS` env variable is set.\n');450      return;451    }452    const ubuntuVersion = await (0, _ubuntuVersion.getUbuntuVersion)();453    if (browserName === 'firefox' && ubuntuVersion === '16.04') throw new Error(`Cannot launch Firefox on Ubuntu 16.04! Minimum required Ubuntu version for Firefox browser is 18.04`);454    if (os.platform() === 'linux') return await (0, _dependencies.validateDependenciesLinux)(sdkLanguage, linuxLddDirectories.map(d => _path.default.join(browserDirectory, d)), dlOpenLibraries);455    if (os.platform() === 'win32' && os.arch() === 'x64') return await (0, _dependencies.validateDependenciesWindows)(windowsExeAndDllDirectories.map(d => _path.default.join(browserDirectory, d)));456  }457  async installDeps(executablesToInstallDeps, dryRun) {458    const executables = this._addRequirementsAndDedupe(executablesToInstallDeps);459    const targets = new Set();460    for (const executable of executables) {461      if (executable._dependencyGroup) targets.add(executable._dependencyGroup);462    }463    targets.add('tools');464    if (os.platform() === 'win32') return await (0, _dependencies.installDependenciesWindows)(targets, dryRun);465    if (os.platform() === 'linux') return await (0, _dependencies.installDependenciesLinux)(targets, dryRun);466  }467  async install(executablesToInstall, forceReinstall) {468    const executables = this._addRequirementsAndDedupe(executablesToInstall);469    await fs.promises.mkdir(registryDirectory, {470      recursive: true471    });472    const lockfilePath = _path.default.join(registryDirectory, '__dirlock');473    const linksDir = _path.default.join(registryDirectory, '.links');474    let releaseLock;475    try {476      releaseLock = await _properLockfile.default.lock(registryDirectory, {477        retries: {478          // Retry 20 times during 10 minutes with479          // exponential back-off.480          // See documentation at: https://www.npmjs.com/package/retry#retrytimeoutsoptions481          retries: 20,482          factor: 1.27579483        },484        onCompromised: err => {485          throw new Error(`${err.message} Path: ${lockfilePath}`);486        },487        lockfilePath488      }); // Create a link first, so that cache validation does not remove our own browsers.489      await fs.promises.mkdir(linksDir, {490        recursive: true491      });492      await fs.promises.writeFile(_path.default.join(linksDir, (0, _utils.calculateSha1)(PACKAGE_PATH)), PACKAGE_PATH); // Remove stale browsers.493      await this._validateInstallationCache(linksDir); // Install browsers for this package.494      for (const executable of executables) {495        if (!executable._install) throw new Error(`ERROR: Playwright does not support installing ${executable.name}`);496        const {497          langName498        } = (0, _userAgent.getClientLanguage)();499        if (!(0, _utils.getAsBooleanFromENV)('CI') && !executable._isHermeticInstallation && !forceReinstall && executable.executablePath(langName)) {500          const command = buildPlaywrightCLICommand(langName, 'install --force ' + executable.name);501          throw new Error('\n' + (0, _utils.wrapInASCIIBox)([`ATTENTION: "${executable.name}" is already installed on the system!`, ``, `"${executable.name}" installation is not hermetic; installing newer version`, `requires *removal* of a current installation first.`, ``, `To *uninstall* current version and re-install latest "${executable.name}":`, ``, `- Close all running instances of "${executable.name}", if any`, `- Use "--force" to install browser:`, ``, `    ${command}`, ``, `<3 Playwright Team`].join('\n'), 1));502        }503        await executable._install();504      }505    } catch (e) {506      if (e.code === 'ELOCKED') {507        const rmCommand = process.platform === 'win32' ? 'rm -R' : 'rm -rf';508        throw new Error('\n' + (0, _utils.wrapInASCIIBox)([`An active lockfile is found at:`, ``, `  ${lockfilePath}`, ``, `Either:`, `- wait a few minutes if other Playwright is installing browsers in parallel`, `- remove lock manually with:`, ``, `    ${rmCommand} ${lockfilePath}`, ``, `<3 Playwright Team`].join('\n'), 1));509      } else {510        throw e;511      }512    } finally {513      if (releaseLock) await releaseLock();514    }515  }516  async _downloadExecutable(descriptor, executablePath, downloadPathTemplate, downloadHostEnv) {517    if (!downloadPathTemplate || !executablePath) throw new Error(`ERROR: Playwright does not support ${descriptor.name} on ${_hostPlatform.hostPlatform}`);518    if (_hostPlatform.hostPlatform === 'generic-linux' || _hostPlatform.hostPlatform === 'generic-linux-arm64') (0, _browserFetcher.logPolitely)('BEWARE: your OS is not officially supported by Playwright; downloading Ubuntu build as a fallback.');519    const downloadHost = downloadHostEnv && (0, _utils.getFromENV)(downloadHostEnv) || (0, _utils.getFromENV)('PLAYWRIGHT_DOWNLOAD_HOST') || 'https://playwright.azureedge.net';520    const downloadPath = util.format(downloadPathTemplate, descriptor.revision);521    const downloadURL = `${downloadHost}/${downloadPath}`;522    const title = `${descriptor.name} v${descriptor.revision}`;523    const downloadFileName = `playwright-download-${descriptor.name}-${_hostPlatform.hostPlatform}-${descriptor.revision}.zip`;524    await (0, _browserFetcher.downloadBrowserWithProgressBar)(title, descriptor.dir, executablePath, downloadURL, downloadFileName).catch(e => {525      throw new Error(`Failed to download ${title}, caused by\n${e.stack}`);526    });527    await fs.promises.writeFile(markerFilePath(descriptor.dir), '');528  }529  async _installMSEdgeChannel(channel, scripts) {530    const scriptArgs = [];531    if (process.platform !== 'linux') {532      const products = JSON.parse(await (0, _netUtils.fetchData)({533        url: 'https://edgeupdates.microsoft.com/api/products'534      }));535      const productName = {536        'msedge': 'Stable',537        'msedge-beta': 'Beta',538        'msedge-dev': 'Dev'539      }[channel];540      const product = products.find(product => product.Product === productName);541      const searchConfig = {542        darwin: {543          platform: 'MacOS',544          arch: 'universal',545          artifact: 'pkg'546        },547        win32: {548          platform: 'Windows',549          arch: 'x64',550          artifact: 'msi'551        }552      }[process.platform];553      const release = searchConfig ? product.Releases.find(release => release.Platform === searchConfig.platform && release.Architecture === searchConfig.arch) : null;554      const artifact = release ? release.Artifacts.find(artifact => artifact.ArtifactName === searchConfig.artifact) : null;555      if (artifact) scriptArgs.push(artifact.Location556      /* url */557      );else throw new Error(`Cannot install ${channel} on ${process.platform}`);558    }559    await this._installChromiumChannel(channel, scripts, scriptArgs);560  }561  async _installChromiumChannel(channel, scripts, scriptArgs = []) {562    const scriptName = scripts[process.platform];563    if (!scriptName) throw new Error(`Cannot install ${channel} on ${process.platform}`);564    const cwd = BIN_PATH;565    const isPowerShell = scriptName.endsWith('.ps1');566    if (isPowerShell) {567      const args = ['-ExecutionPolicy', 'Bypass', '-File', _path.default.join(BIN_PATH, scriptName), ...scriptArgs];568      const {569        code570      } = await (0, _spawnAsync.spawnAsync)('powershell.exe', args, {571        cwd,572        stdio: 'inherit'573      });574      if (code !== 0) throw new Error(`Failed to install ${channel}`);575    } else {576      const {577        command,578        args,579        elevatedPermissions580      } = await (0, _dependencies.transformCommandsForRoot)([`bash "${_path.default.join(BIN_PATH, scriptName)}" ${scriptArgs.join('')}`]);581      if (elevatedPermissions) console.log('Switching to root user to install dependencies...'); // eslint-disable-line no-console582      const {583        code584      } = await (0, _spawnAsync.spawnAsync)(command, args, {585        cwd,586        stdio: 'inherit'587      });588      if (code !== 0) throw new Error(`Failed to install ${channel}`);589    }590  }591  async _validateInstallationCache(linksDir) {592    // 1. Collect used downloads and package descriptors.593    const usedBrowserPaths = new Set();594    for (const fileName of await fs.promises.readdir(linksDir)) {595      const linkPath = _path.default.join(linksDir, fileName);596      let linkTarget = '';597      try {598        linkTarget = (await fs.promises.readFile(linkPath)).toString();599        const browsersJSON = require(_path.default.join(linkTarget, 'browsers.json'));600        const descriptors = readDescriptors(browsersJSON);601        for (const browserName of allDownloadable) {602          // We retain browsers if they are found in the descriptor.603          // Note, however, that there are older versions out in the wild that rely on604          // the "download" field in the browser descriptor and use its value605          // to retain and download browsers.606          // As of v1.10, we decided to abandon "download" field.607          const descriptor = descriptors.find(d => d.name === browserName);608          if (!descriptor) continue;609          const usedBrowserPath = descriptor.dir;610          const browserRevision = parseInt(descriptor.revision, 10); // Old browser installations don't have marker file.611          const shouldHaveMarkerFile = browserName === 'chromium' && browserRevision >= 786218 || browserName === 'firefox' && browserRevision >= 1128 || browserName === 'webkit' && browserRevision >= 1307 || // All new applications have a marker file right away.612          browserName !== 'firefox' && browserName !== 'chromium' && browserName !== 'webkit';613          if (!shouldHaveMarkerFile || (await (0, _fileUtils.existsAsync)(markerFilePath(usedBrowserPath)))) usedBrowserPaths.add(usedBrowserPath);614        }615      } catch (e) {616        await fs.promises.unlink(linkPath).catch(e => {});617      }618    } // 2. Delete all unused browsers.619    if (!(0, _utils.getAsBooleanFromENV)('PLAYWRIGHT_SKIP_BROWSER_GC')) {620      let downloadedBrowsers = (await fs.promises.readdir(registryDirectory)).map(file => _path.default.join(registryDirectory, file));621      downloadedBrowsers = downloadedBrowsers.filter(file => isBrowserDirectory(file));622      const directories = new Set(downloadedBrowsers);623      for (const browserDirectory of usedBrowserPaths) directories.delete(browserDirectory);624      for (const directory of directories) (0, _browserFetcher.logPolitely)('Removing unused browser at ' + directory);625      await (0, _fileUtils.removeFolders)([...directories]);626    }627  }628}629exports.Registry = Registry;630function markerFilePath(browserDirectory) {631  return _path.default.join(browserDirectory, 'INSTALLATION_COMPLETE');632}633function buildPlaywrightCLICommand(sdkLanguage, parameters) {634  switch (sdkLanguage) {635    case 'python':636      return `playwright ${parameters}`;637    case 'java':638      return `mvn exec:java -e -Dexec.mainClass=com.microsoft.playwright.CLI -Dexec.args="${parameters}"`;639    case 'csharp':640      return `pwsh bin\\Debug\\netX\\playwright.ps1 ${parameters}`;641    default:642      return `npx playwright ${parameters}`;643  }644}645async function installDefaultBrowsersForNpmInstall() {646  const defaultBrowserNames = registry.defaultExecutables().map(e => e.name);647  return installBrowsersForNpmInstall(defaultBrowserNames);648}649async function installBrowsersForNpmInstall(browsers) {650  // PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD should have a value of 0 or 1651  if ((0, _utils.getAsBooleanFromENV)('PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD')) {652    (0, _browserFetcher.logPolitely)('Skipping browsers download because `PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD` env variable is set');653    return false;654  }655  const executables = [];656  for (const browserName of browsers) {657    const executable = registry.findExecutable(browserName);658    if (!executable || executable.installType === 'none') throw new Error(`Cannot install ${browserName}`);659    executables.push(executable);660  }661  await registry.install(executables, false662  /* forceReinstall */663  );664}665function findChromiumChannel(sdkLanguage) {666  // Fall back to the stable channels of popular vendors to work out of the box.667  // Null means no installation and no channels found.668  let channel = null;669  for (const name of ['chromium', 'chrome', 'msedge']) {670    try {671      registry.findExecutable(name).executablePathOrDie(sdkLanguage);672      channel = name === 'chromium' ? undefined : name;673      break;674    } catch (e) {}675  }676  if (channel === null) {677    const installCommand = buildPlaywrightCLICommand(sdkLanguage, `install chromium`);678    const prettyMessage = [`No chromium-based browser found on the system.`, `Please run the following command to download one:`, ``, `    ${installCommand}`, ``, `<3 Playwright Team`].join('\n');679    throw new Error('\n' + (0, _utils.wrapInASCIIBox)(prettyMessage, 1));680  }681  return channel;682}683const registry = new Registry(require('../../../browsers.json'));...registry.js
Source:registry.js  
1"use strict";2Object.defineProperty(exports, "__esModule", {3  value: true4});5exports.Registry = void 0;6exports.buildPlaywrightCLICommand = buildPlaywrightCLICommand;7exports.findChromiumChannel = findChromiumChannel;8exports.installBrowsersForNpmInstall = installBrowsersForNpmInstall;9exports.installDefaultBrowsersForNpmInstall = installDefaultBrowsersForNpmInstall;10exports.registryDirectory = exports.registry = void 0;11var os = _interopRequireWildcard(require("os"));12var _path = _interopRequireDefault(require("path"));13var util = _interopRequireWildcard(require("util"));14var fs = _interopRequireWildcard(require("fs"));15var _properLockfile = _interopRequireDefault(require("proper-lockfile"));16var _ubuntuVersion = require("./ubuntuVersion");17var _utils = require("./utils");18var _dependencies = require("./dependencies");19var _browserFetcher = require("./browserFetcher");20function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }21function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }22function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }23/**24 * Copyright 2017 Google Inc. All rights reserved.25 * Modifications copyright (c) Microsoft Corporation.26 *27 * Licensed under the Apache License, Version 2.0 (the "License");28 * you may not use this file except in compliance with the License.29 * You may obtain a copy of the License at30 *31 *     http://www.apache.org/licenses/LICENSE-2.032 *33 * Unless required by applicable law or agreed to in writing, software34 * distributed under the License is distributed on an "AS IS" BASIS,35 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.36 * See the License for the specific language governing permissions and37 * limitations under the License.38 */39const PACKAGE_PATH = _path.default.join(__dirname, '..', '..');40const BIN_PATH = _path.default.join(__dirname, '..', '..', 'bin');41const EXECUTABLE_PATHS = {42  'chromium': {43    'linux': ['chrome-linux', 'chrome'],44    'mac': ['chrome-mac', 'Chromium.app', 'Contents', 'MacOS', 'Chromium'],45    'win': ['chrome-win', 'chrome.exe']46  },47  'firefox': {48    'linux': ['firefox', 'firefox'],49    'mac': ['firefox', 'Nightly.app', 'Contents', 'MacOS', 'firefox'],50    'win': ['firefox', 'firefox.exe']51  },52  'webkit': {53    'linux': ['pw_run.sh'],54    'mac': ['pw_run.sh'],55    'win': ['Playwright.exe']56  },57  'ffmpeg': {58    'linux': ['ffmpeg-linux'],59    'mac': ['ffmpeg-mac'],60    'win': ['ffmpeg-win64.exe']61  }62};63const DOWNLOAD_PATHS = {64  'chromium': {65    'ubuntu18.04': 'builds/chromium/%s/chromium-linux.zip',66    'ubuntu20.04': 'builds/chromium/%s/chromium-linux.zip',67    'ubuntu18.04-arm64': 'builds/chromium/%s/chromium-linux-arm64.zip',68    'ubuntu20.04-arm64': 'builds/chromium/%s/chromium-linux-arm64.zip',69    'mac10.13': 'builds/chromium/%s/chromium-mac.zip',70    'mac10.14': 'builds/chromium/%s/chromium-mac.zip',71    'mac10.15': 'builds/chromium/%s/chromium-mac.zip',72    'mac11': 'builds/chromium/%s/chromium-mac.zip',73    'mac11-arm64': 'builds/chromium/%s/chromium-mac-arm64.zip',74    'mac12': 'builds/chromium/%s/chromium-mac.zip',75    'mac12-arm64': 'builds/chromium/%s/chromium-mac-arm64.zip',76    'win64': 'builds/chromium/%s/chromium-win64.zip'77  },78  'chromium-with-symbols': {79    'ubuntu18.04': 'builds/chromium/%s/chromium-with-symbols-linux.zip',80    'ubuntu20.04': 'builds/chromium/%s/chromium-with-symbols-linux.zip',81    'ubuntu18.04-arm64': 'builds/chromium/%s/chromium-with-symbols-linux-arm64.zip',82    'ubuntu20.04-arm64': 'builds/chromium/%s/chromium-with-symbols-linux-arm64.zip',83    'mac10.13': 'builds/chromium/%s/chromium-with-symbols-mac.zip',84    'mac10.14': 'builds/chromium/%s/chromium-with-symbols-mac.zip',85    'mac10.15': 'builds/chromium/%s/chromium-with-symbols-mac.zip',86    'mac11': 'builds/chromium/%s/chromium-with-symbols-mac.zip',87    'mac11-arm64': 'builds/chromium/%s/chromium-with-symbols-mac-arm64.zip',88    'mac12': 'builds/chromium/%s/chromium-with-symbols-mac.zip',89    'mac12-arm64': 'builds/chromium/%s/chromium-with-symbols-mac-arm64.zip',90    'win64': 'builds/chromium/%s/chromium-with-symbols-win64.zip'91  },92  'firefox': {93    'ubuntu18.04': 'builds/firefox/%s/firefox-ubuntu-18.04.zip',94    'ubuntu20.04': 'builds/firefox/%s/firefox-ubuntu-20.04.zip',95    'ubuntu18.04-arm64': undefined,96    'ubuntu20.04-arm64': 'builds/firefox/%s/firefox-ubuntu-20.04-arm64.zip',97    'mac10.13': 'builds/firefox/%s/firefox-mac-11.zip',98    'mac10.14': 'builds/firefox/%s/firefox-mac-11.zip',99    'mac10.15': 'builds/firefox/%s/firefox-mac-11.zip',100    'mac11': 'builds/firefox/%s/firefox-mac-11.zip',101    'mac11-arm64': 'builds/firefox/%s/firefox-mac-11-arm64.zip',102    'mac12': 'builds/firefox/%s/firefox-mac-11.zip',103    'mac12-arm64': 'builds/firefox/%s/firefox-mac-11-arm64.zip',104    'win64': 'builds/firefox/%s/firefox-win64.zip'105  },106  'firefox-beta': {107    'ubuntu18.04': 'builds/firefox-beta/%s/firefox-beta-ubuntu-18.04.zip',108    'ubuntu20.04': 'builds/firefox-beta/%s/firefox-beta-ubuntu-20.04.zip',109    'ubuntu18.04-arm64': undefined,110    'ubuntu20.04-arm64': undefined,111    'mac10.13': 'builds/firefox-beta/%s/firefox-beta-mac-11.zip',112    'mac10.14': 'builds/firefox-beta/%s/firefox-beta-mac-11.zip',113    'mac10.15': 'builds/firefox-beta/%s/firefox-beta-mac-11.zip',114    'mac11': 'builds/firefox-beta/%s/firefox-beta-mac-11.zip',115    'mac11-arm64': 'builds/firefox-beta/%s/firefox-beta-mac-11-arm64.zip',116    'mac12': 'builds/firefox-beta/%s/firefox-beta-mac-11.zip',117    'mac12-arm64': 'builds/firefox-beta/%s/firefox-beta-mac-11-arm64.zip',118    'win64': 'builds/firefox-beta/%s/firefox-beta-win64.zip'119  },120  'webkit': {121    'ubuntu18.04': 'builds/webkit/%s/webkit-ubuntu-18.04.zip',122    'ubuntu20.04': 'builds/webkit/%s/webkit-ubuntu-20.04.zip',123    'ubuntu18.04-arm64': undefined,124    'ubuntu20.04-arm64': 'builds/webkit/%s/webkit-ubuntu-20.04-arm64.zip',125    'mac10.13': undefined,126    'mac10.14': 'builds/deprecated-webkit-mac-10.14/%s/deprecated-webkit-mac-10.14.zip',127    'mac10.15': 'builds/webkit/%s/webkit-mac-10.15.zip',128    'mac11': 'builds/webkit/%s/webkit-mac-10.15.zip',129    'mac11-arm64': 'builds/webkit/%s/webkit-mac-11-arm64.zip',130    'mac12': 'builds/webkit/%s/webkit-mac-12.zip',131    'mac12-arm64': 'builds/webkit/%s/webkit-mac-12-arm64.zip',132    'win64': 'builds/webkit/%s/webkit-win64.zip'133  },134  'ffmpeg': {135    'ubuntu18.04': 'builds/ffmpeg/%s/ffmpeg-linux.zip',136    'ubuntu20.04': 'builds/ffmpeg/%s/ffmpeg-linux.zip',137    'ubuntu18.04-arm64': 'builds/ffmpeg/%s/ffmpeg-linux-arm64.zip',138    'ubuntu20.04-arm64': 'builds/ffmpeg/%s/ffmpeg-linux-arm64.zip',139    'mac10.13': 'builds/ffmpeg/%s/ffmpeg-mac.zip',140    'mac10.14': 'builds/ffmpeg/%s/ffmpeg-mac.zip',141    'mac10.15': 'builds/ffmpeg/%s/ffmpeg-mac.zip',142    'mac11': 'builds/ffmpeg/%s/ffmpeg-mac.zip',143    'mac11-arm64': 'builds/ffmpeg/%s/ffmpeg-mac-arm64.zip',144    'mac12': 'builds/ffmpeg/%s/ffmpeg-mac.zip',145    'mac12-arm64': 'builds/ffmpeg/%s/ffmpeg-mac-arm64.zip',146    'win64': 'builds/ffmpeg/%s/ffmpeg-win64.zip'147  }148};149const registryDirectory = (() => {150  let result;151  const envDefined = (0, _utils.getFromENV)('PLAYWRIGHT_BROWSERS_PATH');152  if (envDefined === '0') {153    result = _path.default.join(__dirname, '..', '..', '.local-browsers');154  } else if (envDefined) {155    result = envDefined;156  } else {157    let cacheDirectory;158    if (process.platform === 'linux') cacheDirectory = process.env.XDG_CACHE_HOME || _path.default.join(os.homedir(), '.cache');else if (process.platform === 'darwin') cacheDirectory = _path.default.join(os.homedir(), 'Library', 'Caches');else if (process.platform === 'win32') cacheDirectory = process.env.LOCALAPPDATA || _path.default.join(os.homedir(), 'AppData', 'Local');else throw new Error('Unsupported platform: ' + process.platform);159    result = _path.default.join(cacheDirectory, 'ms-playwright');160  }161  if (!_path.default.isAbsolute(result)) {162    // It is important to resolve to the absolute path:163    //   - for unzipping to work correctly;164    //   - so that registry directory matches between installation and execution.165    // INIT_CWD points to the root of `npm/yarn install` and is probably what166    // the user meant when typing the relative path.167    result = _path.default.resolve((0, _utils.getFromENV)('INIT_CWD') || process.cwd(), result);168  }169  return result;170})();171exports.registryDirectory = registryDirectory;172function isBrowserDirectory(browserDirectory) {173  const baseName = _path.default.basename(browserDirectory);174  for (const browserName of allDownloadable) {175    if (baseName.startsWith(browserName + '-')) return true;176  }177  return false;178}179function readDescriptors(browsersJSON) {180  return browsersJSON['browsers'].map(obj => {181    const name = obj.name;182    const revisionOverride = (obj.revisionOverrides || {})[_utils.hostPlatform];183    const revision = revisionOverride || obj.revision;184    const browserDirectoryPrefix = revisionOverride ? `${name}_${_utils.hostPlatform}_special` : `${name}`;185    const descriptor = {186      name,187      revision,188      installByDefault: !!obj.installByDefault,189      // Method `isBrowserDirectory` determines directory to be browser iff190      // it starts with some browser name followed by '-'. Some browser names191      // are prefixes of others, e.g. 'webkit' is a prefix of `webkit-technology-preview`.192      // To avoid older registries erroneously removing 'webkit-technology-preview', we have to193      // ensure that browser folders to never include dashes inside.194      dir: _path.default.join(registryDirectory, browserDirectoryPrefix.replace(/-/g, '_') + '-' + revision)195    };196    return descriptor;197  });198}199const allDownloadable = ['chromium', 'firefox', 'webkit', 'ffmpeg', 'firefox-beta', 'chromium-with-symbols'];200class Registry {201  constructor(browsersJSON) {202    this._executables = void 0;203    const descriptors = readDescriptors(browsersJSON);204    const findExecutablePath = (dir, name) => {205      let tokens = undefined;206      if (_utils.hostPlatform.startsWith('ubuntu')) tokens = EXECUTABLE_PATHS[name]['linux'];else if (_utils.hostPlatform.startsWith('mac')) tokens = EXECUTABLE_PATHS[name]['mac'];else if (_utils.hostPlatform.startsWith('win')) tokens = EXECUTABLE_PATHS[name]['win'];207      return tokens ? _path.default.join(dir, ...tokens) : undefined;208    };209    const executablePathOrDie = (name, e, installByDefault, sdkLanguage) => {210      if (!e) throw new Error(`${name} is not supported on ${_utils.hostPlatform}`);211      const installCommand = buildPlaywrightCLICommand(sdkLanguage, `install${installByDefault ? '' : ' ' + name}`);212      if (!(0, _utils.canAccessFile)(e)) {213        const prettyMessage = [`Looks like Playwright Test or Playwright was just installed or updated.`, `Please run the following command to download new browser${installByDefault ? 's' : ''}:`, ``, `    ${installCommand}`, ``, `<3 Playwright Team`].join('\n');214        throw new Error(`Executable doesn't exist at ${e}\n${(0, _utils.wrapInASCIIBox)(prettyMessage, 1)}`);215      }216      return e;217    };218    this._executables = [];219    const chromium = descriptors.find(d => d.name === 'chromium');220    const chromiumExecutable = findExecutablePath(chromium.dir, 'chromium');221    this._executables.push({222      type: 'browser',223      name: 'chromium',224      browserName: 'chromium',225      directory: chromium.dir,226      executablePath: () => chromiumExecutable,227      executablePathOrDie: sdkLanguage => executablePathOrDie('chromium', chromiumExecutable, chromium.installByDefault, sdkLanguage),228      installType: chromium.installByDefault ? 'download-by-default' : 'download-on-demand',229      validateHostRequirements: sdkLanguage => this._validateHostRequirements(sdkLanguage, 'chromium', chromium.dir, ['chrome-linux'], [], ['chrome-win']),230      _install: () => this._downloadExecutable(chromium, chromiumExecutable, DOWNLOAD_PATHS['chromium'][_utils.hostPlatform], 'PLAYWRIGHT_CHROMIUM_DOWNLOAD_HOST'),231      _dependencyGroup: 'chromium'232    });233    const chromiumWithSymbols = descriptors.find(d => d.name === 'chromium-with-symbols');234    const chromiumWithSymbolsExecutable = findExecutablePath(chromiumWithSymbols.dir, 'chromium');235    this._executables.push({236      type: 'tool',237      name: 'chromium-with-symbols',238      browserName: 'chromium',239      directory: chromiumWithSymbols.dir,240      executablePath: () => chromiumWithSymbolsExecutable,241      executablePathOrDie: sdkLanguage => executablePathOrDie('chromium-with-symbols', chromiumWithSymbolsExecutable, chromiumWithSymbols.installByDefault, sdkLanguage),242      installType: chromiumWithSymbols.installByDefault ? 'download-by-default' : 'download-on-demand',243      validateHostRequirements: sdkLanguage => this._validateHostRequirements(sdkLanguage, 'chromium', chromiumWithSymbols.dir, ['chrome-linux'], [], ['chrome-win']),244      _install: () => this._downloadExecutable(chromiumWithSymbols, chromiumWithSymbolsExecutable, DOWNLOAD_PATHS['chromium-with-symbols'][_utils.hostPlatform], 'PLAYWRIGHT_CHROMIUM_DOWNLOAD_HOST'),245      _dependencyGroup: 'chromium'246    });247    this._executables.push(this._createChromiumChannel('chrome', {248      'linux': '/opt/google/chrome/chrome',249      'darwin': '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome',250      'win32': `\\Google\\Chrome\\Application\\chrome.exe`251    }, () => this._installChromiumChannel('chrome', {252      'linux': 'reinstall_chrome_stable_linux.sh',253      'darwin': 'reinstall_chrome_stable_mac.sh',254      'win32': 'reinstall_chrome_stable_win.ps1'255    })));256    this._executables.push(this._createChromiumChannel('chrome-beta', {257      'linux': '/opt/google/chrome-beta/chrome',258      'darwin': '/Applications/Google Chrome Beta.app/Contents/MacOS/Google Chrome Beta',259      'win32': `\\Google\\Chrome Beta\\Application\\chrome.exe`260    }, () => this._installChromiumChannel('chrome-beta', {261      'linux': 'reinstall_chrome_beta_linux.sh',262      'darwin': 'reinstall_chrome_beta_mac.sh',263      'win32': 'reinstall_chrome_beta_win.ps1'264    })));265    this._executables.push(this._createChromiumChannel('chrome-dev', {266      'linux': '/opt/google/chrome-unstable/chrome',267      'darwin': '/Applications/Google Chrome Dev.app/Contents/MacOS/Google Chrome Dev',268      'win32': `\\Google\\Chrome Dev\\Application\\chrome.exe`269    }));270    this._executables.push(this._createChromiumChannel('chrome-canary', {271      'linux': '',272      'darwin': '/Applications/Google Chrome Canary.app/Contents/MacOS/Google Chrome Canary',273      'win32': `\\Google\\Chrome SxS\\Application\\chrome.exe`274    }));275    this._executables.push(this._createChromiumChannel('msedge', {276      'linux': '/opt/microsoft/msedge/msedge',277      'darwin': '/Applications/Microsoft Edge.app/Contents/MacOS/Microsoft Edge',278      'win32': `\\Microsoft\\Edge\\Application\\msedge.exe`279    }, () => this._installMSEdgeChannel('msedge', {280      'linux': 'reinstall_msedge_stable_linux.sh',281      'darwin': 'reinstall_msedge_stable_mac.sh',282      'win32': 'reinstall_msedge_stable_win.ps1'283    })));284    this._executables.push(this._createChromiumChannel('msedge-beta', {285      'linux': '/opt/microsoft/msedge-beta/msedge',286      'darwin': '/Applications/Microsoft Edge Beta.app/Contents/MacOS/Microsoft Edge Beta',287      'win32': `\\Microsoft\\Edge Beta\\Application\\msedge.exe`288    }, () => this._installMSEdgeChannel('msedge-beta', {289      'darwin': 'reinstall_msedge_beta_mac.sh',290      'linux': 'reinstall_msedge_beta_linux.sh',291      'win32': 'reinstall_msedge_beta_win.ps1'292    })));293    this._executables.push(this._createChromiumChannel('msedge-dev', {294      'linux': '/opt/microsoft/msedge-dev/msedge',295      'darwin': '/Applications/Microsoft Edge Dev.app/Contents/MacOS/Microsoft Edge Dev',296      'win32': `\\Microsoft\\Edge Dev\\Application\\msedge.exe`297    }, () => this._installMSEdgeChannel('msedge-dev', {298      'darwin': 'reinstall_msedge_dev_mac.sh',299      'linux': 'reinstall_msedge_dev_linux.sh',300      'win32': 'reinstall_msedge_dev_win.ps1'301    })));302    this._executables.push(this._createChromiumChannel('msedge-canary', {303      'linux': '',304      'darwin': '/Applications/Microsoft Edge Canary.app/Contents/MacOS/Microsoft Edge Canary',305      'win32': `\\Microsoft\\Edge SxS\\Application\\msedge.exe`306    }));307    const firefox = descriptors.find(d => d.name === 'firefox');308    const firefoxExecutable = findExecutablePath(firefox.dir, 'firefox');309    this._executables.push({310      type: 'browser',311      name: 'firefox',312      browserName: 'firefox',313      directory: firefox.dir,314      executablePath: () => firefoxExecutable,315      executablePathOrDie: sdkLanguage => executablePathOrDie('firefox', firefoxExecutable, firefox.installByDefault, sdkLanguage),316      installType: firefox.installByDefault ? 'download-by-default' : 'download-on-demand',317      validateHostRequirements: sdkLanguage => this._validateHostRequirements(sdkLanguage, 'firefox', firefox.dir, ['firefox'], [], ['firefox']),318      _install: () => this._downloadExecutable(firefox, firefoxExecutable, DOWNLOAD_PATHS['firefox'][_utils.hostPlatform], 'PLAYWRIGHT_FIREFOX_DOWNLOAD_HOST'),319      _dependencyGroup: 'firefox'320    });321    const firefoxBeta = descriptors.find(d => d.name === 'firefox-beta');322    const firefoxBetaExecutable = findExecutablePath(firefoxBeta.dir, 'firefox');323    this._executables.push({324      type: 'tool',325      name: 'firefox-beta',326      browserName: 'firefox',327      directory: firefoxBeta.dir,328      executablePath: () => firefoxBetaExecutable,329      executablePathOrDie: sdkLanguage => executablePathOrDie('firefox-beta', firefoxBetaExecutable, firefoxBeta.installByDefault, sdkLanguage),330      installType: firefoxBeta.installByDefault ? 'download-by-default' : 'download-on-demand',331      validateHostRequirements: sdkLanguage => this._validateHostRequirements(sdkLanguage, 'firefox', firefoxBeta.dir, ['firefox'], [], ['firefox']),332      _install: () => this._downloadExecutable(firefoxBeta, firefoxBetaExecutable, DOWNLOAD_PATHS['firefox-beta'][_utils.hostPlatform], 'PLAYWRIGHT_FIREFOX_DOWNLOAD_HOST'),333      _dependencyGroup: 'firefox'334    });335    const webkit = descriptors.find(d => d.name === 'webkit');336    const webkitExecutable = findExecutablePath(webkit.dir, 'webkit');337    const webkitLinuxLddDirectories = [_path.default.join('minibrowser-gtk'), _path.default.join('minibrowser-gtk', 'bin'), _path.default.join('minibrowser-gtk', 'lib'), _path.default.join('minibrowser-wpe'), _path.default.join('minibrowser-wpe', 'bin'), _path.default.join('minibrowser-wpe', 'lib')];338    this._executables.push({339      type: 'browser',340      name: 'webkit',341      browserName: 'webkit',342      directory: webkit.dir,343      executablePath: () => webkitExecutable,344      executablePathOrDie: sdkLanguage => executablePathOrDie('webkit', webkitExecutable, webkit.installByDefault, sdkLanguage),345      installType: webkit.installByDefault ? 'download-by-default' : 'download-on-demand',346      validateHostRequirements: sdkLanguage => this._validateHostRequirements(sdkLanguage, 'webkit', webkit.dir, webkitLinuxLddDirectories, ['libGLESv2.so.2', 'libx264.so'], ['']),347      _install: () => this._downloadExecutable(webkit, webkitExecutable, DOWNLOAD_PATHS['webkit'][_utils.hostPlatform], 'PLAYWRIGHT_WEBKIT_DOWNLOAD_HOST'),348      _dependencyGroup: 'webkit'349    });350    const ffmpeg = descriptors.find(d => d.name === 'ffmpeg');351    const ffmpegExecutable = findExecutablePath(ffmpeg.dir, 'ffmpeg');352    this._executables.push({353      type: 'tool',354      name: 'ffmpeg',355      browserName: undefined,356      directory: ffmpeg.dir,357      executablePath: () => ffmpegExecutable,358      executablePathOrDie: sdkLanguage => executablePathOrDie('ffmpeg', ffmpegExecutable, ffmpeg.installByDefault, sdkLanguage),359      installType: ffmpeg.installByDefault ? 'download-by-default' : 'download-on-demand',360      validateHostRequirements: () => Promise.resolve(),361      _install: () => this._downloadExecutable(ffmpeg, ffmpegExecutable, DOWNLOAD_PATHS['ffmpeg'][_utils.hostPlatform], 'PLAYWRIGHT_FFMPEG_DOWNLOAD_HOST'),362      _dependencyGroup: 'tools'363    });364  }365  _createChromiumChannel(name, lookAt, install) {366    const executablePath = (sdkLanguage, shouldThrow) => {367      const suffix = lookAt[process.platform];368      if (!suffix) {369        if (shouldThrow) throw new Error(`Chromium distribution '${name}' is not supported on ${process.platform}`);370        return undefined;371      }372      const prefixes = process.platform === 'win32' ? [process.env.LOCALAPPDATA, process.env.PROGRAMFILES, process.env['PROGRAMFILES(X86)']].filter(Boolean) : [''];373      for (const prefix of prefixes) {374        const executablePath = _path.default.join(prefix, suffix);375        if ((0, _utils.canAccessFile)(executablePath)) return executablePath;376      }377      if (!shouldThrow) return undefined;378      const location = prefixes.length ? ` at ${_path.default.join(prefixes[0], suffix)}` : ``; // TODO: language-specific error message379      const installation = install ? `\nRun "${buildPlaywrightCLICommand(sdkLanguage, 'install ' + name)}"` : '';380      throw new Error(`Chromium distribution '${name}' is not found${location}${installation}`);381    };382    return {383      type: 'channel',384      name,385      browserName: 'chromium',386      directory: undefined,387      executablePath: sdkLanguage => executablePath(sdkLanguage, false),388      executablePathOrDie: sdkLanguage => executablePath(sdkLanguage, true),389      installType: install ? 'install-script' : 'none',390      validateHostRequirements: () => Promise.resolve(),391      _install: install392    };393  }394  executables() {395    return this._executables;396  }397  findExecutable(name) {398    return this._executables.find(b => b.name === name);399  }400  defaultExecutables() {401    return this._executables.filter(e => e.installType === 'download-by-default');402  }403  _addRequirementsAndDedupe(executables) {404    const set = new Set();405    for (const executable of executables) {406      set.add(executable);407      if (executable.browserName === 'chromium') set.add(this.findExecutable('ffmpeg'));408    }409    return Array.from(set);410  }411  async _validateHostRequirements(sdkLanguage, browserName, browserDirectory, linuxLddDirectories, dlOpenLibraries, windowsExeAndDllDirectories) {412    if ((0, _utils.getAsBooleanFromENV)('PLAYWRIGHT_SKIP_VALIDATE_HOST_REQUIREMENTS')) {413      process.stdout.write('Skipping host requirements validation logic because `PLAYWRIGHT_SKIP_VALIDATE_HOST_REQUIREMENTS` env variable is set.\n');414      return;415    }416    const ubuntuVersion = await (0, _ubuntuVersion.getUbuntuVersion)();417    if (browserName === 'firefox' && ubuntuVersion === '16.04') throw new Error(`Cannot launch Firefox on Ubuntu 16.04! Minimum required Ubuntu version for Firefox browser is 18.04`);418    if (os.platform() === 'linux') return await (0, _dependencies.validateDependenciesLinux)(sdkLanguage, linuxLddDirectories.map(d => _path.default.join(browserDirectory, d)), dlOpenLibraries);419    if (os.platform() === 'win32' && os.arch() === 'x64') return await (0, _dependencies.validateDependenciesWindows)(windowsExeAndDllDirectories.map(d => _path.default.join(browserDirectory, d)));420  }421  async installDeps(executablesToInstallDeps, dryRun) {422    const executables = this._addRequirementsAndDedupe(executablesToInstallDeps);423    const targets = new Set();424    for (const executable of executables) {425      if (executable._dependencyGroup) targets.add(executable._dependencyGroup);426    }427    targets.add('tools');428    if (os.platform() === 'win32') return await (0, _dependencies.installDependenciesWindows)(targets, dryRun);429    if (os.platform() === 'linux') return await (0, _dependencies.installDependenciesLinux)(targets, dryRun);430  }431  async install(executablesToInstall) {432    const executables = this._addRequirementsAndDedupe(executablesToInstall);433    await fs.promises.mkdir(registryDirectory, {434      recursive: true435    });436    const lockfilePath = _path.default.join(registryDirectory, '__dirlock');437    const linksDir = _path.default.join(registryDirectory, '.links');438    let releaseLock;439    try {440      releaseLock = await _properLockfile.default.lock(registryDirectory, {441        retries: {442          // Retry 20 times during 10 minutes with443          // exponential back-off.444          // See documentation at: https://www.npmjs.com/package/retry#retrytimeoutsoptions445          retries: 20,446          factor: 1.27579447        },448        onCompromised: err => {449          throw new Error(`${err.message} Path: ${lockfilePath}`);450        },451        lockfilePath452      }); // Create a link first, so that cache validation does not remove our own browsers.453      await fs.promises.mkdir(linksDir, {454        recursive: true455      });456      await fs.promises.writeFile(_path.default.join(linksDir, (0, _utils.calculateSha1)(PACKAGE_PATH)), PACKAGE_PATH); // Remove stale browsers.457      await this._validateInstallationCache(linksDir); // Install browsers for this package.458      for (const executable of executables) {459        if (executable._install) await executable._install();else throw new Error(`ERROR: Playwright does not support installing ${executable.name}`);460      }461    } catch (e) {462      if (e.code === 'ELOCKED') {463        const rmCommand = process.platform === 'win32' ? 'rm -R' : 'rm -rf';464        throw new Error('\n' + (0, _utils.wrapInASCIIBox)([`An active lockfile is found at:`, ``, `  ${lockfilePath}`, ``, `Either:`, `- wait a few minutes if other Playwright is installing browsers in parallel`, `- remove lock manually with:`, ``, `    ${rmCommand} ${lockfilePath}`, ``, `<3 Playwright Team`].join('\n'), 1));465      } else {466        throw e;467      }468    } finally {469      if (releaseLock) await releaseLock();470    }471  }472  async _downloadExecutable(descriptor, executablePath, downloadPathTemplate, downloadHostEnv) {473    if (!downloadPathTemplate || !executablePath) throw new Error(`ERROR: Playwright does not support ${descriptor.name} on ${_utils.hostPlatform}`);474    const downloadHost = downloadHostEnv && (0, _utils.getFromENV)(downloadHostEnv) || (0, _utils.getFromENV)('PLAYWRIGHT_DOWNLOAD_HOST') || 'https://playwright.azureedge.net';475    const downloadPath = util.format(downloadPathTemplate, descriptor.revision);476    const downloadURL = `${downloadHost}/${downloadPath}`;477    const title = `${descriptor.name} v${descriptor.revision}`;478    const downloadFileName = `playwright-download-${descriptor.name}-${_utils.hostPlatform}-${descriptor.revision}.zip`;479    await (0, _browserFetcher.downloadBrowserWithProgressBar)(title, descriptor.dir, executablePath, downloadURL, downloadFileName).catch(e => {480      throw new Error(`Failed to download ${title}, caused by\n${e.stack}`);481    });482    await fs.promises.writeFile(markerFilePath(descriptor.dir), '');483  }484  async _installMSEdgeChannel(channel, scripts) {485    const scriptArgs = [];486    if (process.platform !== 'linux') {487      const products = JSON.parse(await (0, _utils.fetchData)({488        url: 'https://edgeupdates.microsoft.com/api/products'489      }));490      const productName = {491        'msedge': 'Stable',492        'msedge-beta': 'Beta',493        'msedge-dev': 'Dev'494      }[channel];495      const product = products.find(product => product.Product === productName);496      const searchConfig = {497        darwin: {498          platform: 'MacOS',499          arch: 'universal',500          artifact: 'pkg'501        },502        win32: {503          platform: 'Windows',504          arch: 'x64',505          artifact: 'msi'506        }507      }[process.platform];508      const release = searchConfig ? product.Releases.find(release => release.Platform === searchConfig.platform && release.Architecture === searchConfig.arch) : null;509      const artifact = release ? release.Artifacts.find(artifact => artifact.ArtifactName === searchConfig.artifact) : null;510      if (artifact) scriptArgs.push(artifact.Location511      /* url */512      );else throw new Error(`Cannot install ${channel} on ${process.platform}`);513    }514    await this._installChromiumChannel(channel, scripts, scriptArgs);515  }516  async _installChromiumChannel(channel, scripts, scriptArgs = []) {517    const scriptName = scripts[process.platform];518    if (!scriptName) throw new Error(`Cannot install ${channel} on ${process.platform}`);519    const cwd = BIN_PATH;520    const isPowerShell = scriptName.endsWith('.ps1');521    if (isPowerShell) {522      const args = ['-ExecutionPolicy', 'Bypass', '-File', _path.default.join(BIN_PATH, scriptName), ...scriptArgs];523      const {524        code525      } = await (0, _utils.spawnAsync)('powershell.exe', args, {526        cwd,527        stdio: 'inherit'528      });529      if (code !== 0) throw new Error(`Failed to install ${channel}`);530    } else {531      const {532        command,533        args,534        elevatedPermissions535      } = await (0, _utils.transformCommandsForRoot)([`bash ${_path.default.join(BIN_PATH, scriptName)} ${scriptArgs.join('')}`]);536      if (elevatedPermissions) console.log('Switching to root user to install dependencies...'); // eslint-disable-line no-console537      const {538        code539      } = await (0, _utils.spawnAsync)(command, args, {540        cwd,541        stdio: 'inherit'542      });543      if (code !== 0) throw new Error(`Failed to install ${channel}`);544    }545  }546  async _validateInstallationCache(linksDir) {547    // 1. Collect used downloads and package descriptors.548    const usedBrowserPaths = new Set();549    for (const fileName of await fs.promises.readdir(linksDir)) {550      const linkPath = _path.default.join(linksDir, fileName);551      let linkTarget = '';552      try {553        linkTarget = (await fs.promises.readFile(linkPath)).toString();554        const browsersJSON = require(_path.default.join(linkTarget, 'browsers.json'));555        const descriptors = readDescriptors(browsersJSON);556        for (const browserName of allDownloadable) {557          // We retain browsers if they are found in the descriptor.558          // Note, however, that there are older versions out in the wild that rely on559          // the "download" field in the browser descriptor and use its value560          // to retain and download browsers.561          // As of v1.10, we decided to abandon "download" field.562          const descriptor = descriptors.find(d => d.name === browserName);563          if (!descriptor) continue;564          const usedBrowserPath = descriptor.dir;565          const browserRevision = parseInt(descriptor.revision, 10); // Old browser installations don't have marker file.566          const shouldHaveMarkerFile = browserName === 'chromium' && browserRevision >= 786218 || browserName === 'firefox' && browserRevision >= 1128 || browserName === 'webkit' && browserRevision >= 1307 || // All new applications have a marker file right away.567          browserName !== 'firefox' && browserName !== 'chromium' && browserName !== 'webkit';568          if (!shouldHaveMarkerFile || (await (0, _utils.existsAsync)(markerFilePath(usedBrowserPath)))) usedBrowserPaths.add(usedBrowserPath);569        }570      } catch (e) {571        await fs.promises.unlink(linkPath).catch(e => {});572      }573    } // 2. Delete all unused browsers.574    if (!(0, _utils.getAsBooleanFromENV)('PLAYWRIGHT_SKIP_BROWSER_GC')) {575      let downloadedBrowsers = (await fs.promises.readdir(registryDirectory)).map(file => _path.default.join(registryDirectory, file));576      downloadedBrowsers = downloadedBrowsers.filter(file => isBrowserDirectory(file));577      const directories = new Set(downloadedBrowsers);578      for (const browserDirectory of usedBrowserPaths) directories.delete(browserDirectory);579      for (const directory of directories) (0, _browserFetcher.logPolitely)('Removing unused browser at ' + directory);580      await (0, _utils.removeFolders)([...directories]);581    }582  }583}584exports.Registry = Registry;585function markerFilePath(browserDirectory) {586  return _path.default.join(browserDirectory, 'INSTALLATION_COMPLETE');587}588function buildPlaywrightCLICommand(sdkLanguage, parameters) {589  switch (sdkLanguage) {590    case 'python':591      return `playwright ${parameters}`;592    case 'java':593      return `mvn exec:java -e -Dexec.mainClass=com.microsoft.playwright.CLI -Dexec.args="${parameters}"`;594    case 'csharp':595      return `playwright ${parameters}`;596    default:597      return `npx playwright ${parameters}`;598  }599}600async function installDefaultBrowsersForNpmInstall() {601  const defaultBrowserNames = registry.defaultExecutables().map(e => e.name);602  return installBrowsersForNpmInstall(defaultBrowserNames);603}604async function installBrowsersForNpmInstall(browsers) {605  // PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD should have a value of 0 or 1606  if ((0, _utils.getAsBooleanFromENV)('PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD')) {607    (0, _browserFetcher.logPolitely)('Skipping browsers download because `PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD` env variable is set');608    return false;609  }610  const executables = [];611  for (const browserName of browsers) {612    const executable = registry.findExecutable(browserName);613    if (!executable || executable.installType === 'none') throw new Error(`Cannot install ${browserName}`);614    executables.push(executable);615  }616  await registry.install(executables);617}618function findChromiumChannel(sdkLanguage) {619  // Fall back to the stable channels of popular vendors to work out of the box.620  // Null means no installation and no channels found.621  let channel = null;622  for (const name of ['chromium', 'chrome', 'msedge']) {623    try {624      registry.findExecutable(name).executablePathOrDie(sdkLanguage);625      channel = name === 'chromium' ? undefined : name;626      break;627    } catch (e) {}628  }629  if (channel === null) {630    const installCommand = buildPlaywrightCLICommand(sdkLanguage, `install chromium`);631    const prettyMessage = [`No chromium-based browser found on the system.`, `Please run the following command to download one:`, ``, `    ${installCommand}`, ``, `<3 Playwright Team`].join('\n');632    throw new Error('\n' + (0, _utils.wrapInASCIIBox)(prettyMessage, 1));633  }634  return channel;635}636const registry = new Registry(require('../../browsers.json'));...dependencies.js
Source:dependencies.js  
...39  // The table with versions is taken from: https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-osversioninfoexw#remarks40  // Windows 7 is not supported and is encoded as `6.1`.41  return major > 6 || major === 6 && minor > 1;42}43async function installDependenciesWindows(targets, dryRun) {44  if (targets.has('chromium')) {45    const command = 'powershell.exe';46    const args = ['-ExecutionPolicy', 'Bypass', '-File', _path.default.join(BIN_DIRECTORY, 'install_media_pack.ps1')];47    if (dryRun) {48      console.log(`${command} ${quoteProcessArgs(args).join(' ')}`); // eslint-disable-line no-console49      return;50    }51    const {52      code53    } = await utils.spawnAsync(command, args, {54      cwd: BIN_DIRECTORY,55      stdio: 'inherit'56    });57    if (code !== 0) throw new Error('Failed to install windows dependencies!');...Using AI Code Generation
1const { installDependenciesWindows } = require("playwright/lib/utils/registry");2const { chromium } = require("playwright");3(async () => {4  await installDependenciesWindows();5  const browser = await chromium.launch();6  const context = await browser.newContext();7  const page = await context.newPage();8  await page.screenshot({ path: "example.png" });9  await browser.close();10})();11const { installDependenciesMac } = require("playwright/lib/utils/registry");12const { chromium } = require("playwright");13(async () => {14  await installDependenciesMac();15  const browser = await chromium.launch();16  const context = await browser.newContext();17  const page = await context.newPage();18  await page.screenshot({ path: "example.png" });19  await browser.close();20})();21const { installDependenciesLinux } = require("playwright/lib/utils/registry");22const { chromium } = require("playwright");23(async () => {24  await installDependenciesLinux();25  const browser = await chromium.launch();26  const context = await browser.newContext();27  const page = await context.newPage();28  await page.screenshot({ path: "example.png" });29  await browser.close();30})();31const { chromium } = require("playwright");32(async () => {33  const browser = await chromium.launch();34  const context = await browser.newContext();35  const page = await context.newPage();36  await page.screenshot({ path: "example.png" });37  await browser.close();38})();39const { chromium } = require("playwright");40(async () => {41  const browser = await chromium.launch({42  });43  const context = await browser.newContext();44  const page = await context.newPage();45  await page.goto("httpsUsing AI Code Generation
1const { installDependenciesWindows } = require('playwright/lib/server/installDeps');2const { installDependencies } = require('playwright/lib/server/installDeps');3const { installDependenciesMac } = require('playwright/lib/server/installDeps');4const { installDependenciesLinux } = require('playwright/lib/server/installDeps');5const { installDependenciesUbuntu } = require('playwright/lib/server/installDeps');6const { installDependenciesDebian } = require('playwright/lib/server/installDeps');7const { installDependenciesFedora } = require('playwright/lib/server/installDeps');8const { installDependenciesCentos } = require('playwright/lib/server/installDeps');9const { installDependenciesRedHat } = require('playwright/lib/server/installDeps');10const { installDependenciesArch } = require('playwright/lib/server/installDeps');11const { installDependenciesOpenSUSE } = require('playwright/lib/server/installDeps');12const { installDependenciesAlpine } = require('playwright/lib/server/installDeps');13const { installDependenciesAmazon } = require('playwright/lib/server/installDeps');14const { installDependenciesOracle } = require('playwright/lib/server/installDeps');15const { installDependenciesSUSE } = require('playwright/lib/server/installDeps');16const { installDependenciesRHEL } = require('playwright/lib/server/installDeps');17installDependenciesWindows();18installDependencies();19installDependenciesMac();20installDependenciesLinux();21installDependenciesUbuntu();22installDependenciesDebian();23installDependenciesFedora();24installDependenciesCentos();25installDependenciesRedHat();26installDependenciesArch();27installDependenciesOpenSUSE();28installDependenciesAlpine();29installDependenciesAmazon();30installDependenciesOracle();31installDependenciesSUSE();32installDependenciesRHEL();33const playwright = require('playwright');34const { installDependenciesWindows } = playwright.default;35const { installDependencies } = playwright.default;36const { installDependenciesMac } = playwright.default;37const { installDependenciesLinux } = playwright.default;38const { installDependenciesUbuntu } = playwright.default;39const { installDependenciesDebian } = playwright.default;40const { installDependenciesFedora } = playwright.default;41const { installDependenciesCentos } = playwright.default;42const { installDependenciesRedHat } = playwright.default;Using AI Code Generation
1const { installDependenciesWindows } = require('playwright/lib/server/installDeps');2const { chromium } = require('playwright');3const { BrowserType } = require('playwright/lib/server/browserType');4const { BrowserServer } = require('playwright/lib/server/browserServer');5const { BrowserContext } = require('playwright/lib/server/browserContext');6const { Browser } = require('playwright/lib/server/browser');7const { Page } = require('playwright/lib/server/page');8const { debugLogger } = require('playwright/lib/utils/debugLogger');9const { Connection } = require('playwright/lib/server/connection');10const { ProgressController } = require('playwright/lib/server/progress');11const { TimeoutSettings } = require('playwright/lib/server/timeoutSettings');12const { Events } = require('playwright/lib/server/events');13const { helper } = require('playwright/lib/server/helper');14const path = require('path');15const fs = require('fs');16const os = require('os');17const util = require('util');18const { spawn } = require('child_process');19const { assert } = require('console');20const readFileAsync = util.promisify(fs.readFile);21const writeFileAsync = util.promisify(fs.writeFile);22const browserName = 'chromium';23const browserType = chromium;24const browserOptions = {25};26const browserTypeOptions = {};27const browserServerOptions = {};28const browserContextOptions = {};29const pageOptions = {};30const logger = debugLogger(browserName);31const progressController = new ProgressController(logger, browserName);32const timeoutSettings = new TimeoutSettings();33const connection = new Connection();34connection.on(Events.BrowserContext.Close, () => {35  console.log('BrowserContext Close');36});37connection.on(Events.BrowserContext.Page, (page) => {38  console.log('BrowserContext Page');39});40connection.on(Events.BrowserContext.Close, () => {41  console.log('BrowserContext Close');42});43connection.on(Events.BrowserContext.Page, (page) => {44  console.log('BrowserContext Page');45});46connection.on(Events.BrowserContext.Close, () => {47  console.log('BrowserContext Close');48});49connection.on(Events.BrowserContext.Page, (page) => {50  console.log('BrowserContext Page');51});52connection.on(Events.BrowserContext.Close, () => {53  console.log('Using AI Code Generation
1const { installDependenciesWindows } = require('playwright/lib/utils/installDeps');2installDependenciesWindows();3### installDependenciesWindows(options)4const { installDependenciesWindows } = require('playwright/lib/utils/installDeps');5await installDependenciesWindows({6  dir: path.join(__dirname, 'ms-playwright'),7  proxy: {Using AI Code Generation
1const { installDependenciesWindows } = require('playwright/lib/utils/registry');2installDependenciesWindows();3const { installDependenciesWindows } = require('playwright/lib/utils/registry');4await installDependenciesWindows();5const { installDependenciesLinux } = require('playwright/lib/utils/registry');6await installDependenciesLinux();7const { installDependenciesMac } = require('playwright/lib/utils/registry');8await installDependenciesMac();9const { installDependencies } = require('playwright/lib/utils/registry');10await installDependencies();11const { installBrowsersWithProgressBar } = require('playwright/lib/utils/registry');12await installBrowsersWithProgressBar();13const { installBrowsersWithProgressBar } = require('playwright/lib/utils/registry');14await installBrowsersWithProgressBar();15const { installBrowserWithProgressBar } = require('playwright/lib/utils/registry');16await installBrowserWithProgressBar(browserName);17const { downloadBrowserWithProgressBar } = require('playwright/lib/utils/registry');18await downloadBrowserWithProgressBar(browserName);19const { downloadBrowser } = require('playwright/lib/utils/registry');20await downloadBrowser(browserName);21const { extractBrowser } = require('playwright/lib/utils/registry');22await extractBrowser(browserName);23const { getBrowserDirectory } = require('playwright/lib/utils/registry');24const browserDirectory = getBrowserDirectory(browserName);25const { getBrowserExecutablePath }Using AI Code Generation
1const playwright = require('playwright');2const installDependenciesWindows = async () => {3  try {4    await playwright.internal.installDependenciesWindows();5    console.log('Dependencies installed successfully');6  } catch (e) {7    console.log('Error while installing dependencies', e);8  }9};10installDependenciesWindows();11const playwright = require('playwright');12const installDependenciesMac = async () => {13  try {14    await playwright.internal.installDependenciesMac();15    console.log('Dependencies installed successfully');16  } catch (e) {17    console.log('Error while installing dependencies', e);18  }19};20installDependenciesMac();21const playwright = require('playwright');22const installDependenciesLinux = async () => {23  try {24    await playwright.internal.installDependenciesLinux();25    console.log('Dependencies installed successfully');26  } catch (e) {27    console.log('Error while installing dependencies', e);28  }29};30installDependenciesLinux();31### Install dependencies on Linux (Ubuntu)32const playwright = require('playwright');33const installDependenciesLinuxUbuntu = async () => {34  try {35    await playwright.internal.installDependenciesLinuxUbuntu();36    console.log('Dependencies installed successfully');37  } catch (e) {38    console.log('Error while installing dependencies', e);39  }40};41installDependenciesLinuxUbuntu();42### Install dependencies on Linux (Debian)43const playwright = require('playwright');44const installDependenciesLinuxDebian = async () => {45  try {LambdaTest’s Playwright tutorial will give you a broader idea about the Playwright automation framework, its unique features, and use cases with examples to exceed your understanding of Playwright testing. This tutorial will give A to Z guidance, from installing the Playwright framework to some best practices and advanced concepts.
Get 100 minutes of automation test minutes FREE!!
