chrome-location2
Version:
Approximates the current location of the Chrome browser across platforms.
390 lines (389 loc) • 16.1 kB
JavaScript
import * as __WEBPACK_EXTERNAL_MODULE_fs__ from "fs";
import * as __WEBPACK_EXTERNAL_MODULE_userhome__ from "userhome";
import * as __WEBPACK_EXTERNAL_MODULE_node_path_c5b9b54f__ from "node:path";
import * as __WEBPACK_EXTERNAL_MODULE_which__ from "which";
import * as __WEBPACK_EXTERNAL_MODULE_child_process__ from "child_process";
import * as __WEBPACK_EXTERNAL_MODULE_node_fs_5ea92f0c__ from "node:fs";
function scanOsxPath(allowFallback = false, deps) {
const f = (null == deps ? void 0 : deps.fs) ?? __WEBPACK_EXTERNAL_MODULE_fs__["default"];
const uh = (null == deps ? void 0 : deps.userhome) ?? __WEBPACK_EXTERNAL_MODULE_userhome__["default"];
const envPath = process.env.CHROME_FOR_TESTING_PATH || process.env.CHROMIUM_BINARY || process.env.CHROME_BINARY;
if (envPath && f.existsSync(envPath)) return envPath;
const cft = '/Applications/Google Chrome for Testing.app/Contents/MacOS/Google Chrome for Testing';
if (f.existsSync(cft)) return cft;
const chromeChannels = [
{
app: 'Google Chrome.app',
exec: 'Google Chrome'
},
{
app: 'Google Chrome Beta.app',
exec: 'Google Chrome Beta'
},
{
app: 'Google Chrome Dev.app',
exec: 'Google Chrome Dev'
},
{
app: 'Google Chrome Canary.app',
exec: 'Google Chrome Canary'
}
];
const chromium = {
app: 'Chromium.app',
exec: 'Chromium'
};
const apps = allowFallback ? [
...chromeChannels,
chromium
] : [
chromeChannels[0]
];
const systemBase = '/Applications';
const userBase = uh('Applications');
for (const { app, exec } of apps){
const systemPath = `${systemBase}/${app}/Contents/MacOS/${exec}`;
if (f.existsSync(systemPath)) return systemPath;
const userPath = `${userBase}/${app}/Contents/MacOS/${exec}`;
if (f.existsSync(userPath)) return userPath;
}
return null;
}
function scanWindowsPath(allowFallback = false, deps) {
const f = (null == deps ? void 0 : deps.fs) ?? __WEBPACK_EXTERNAL_MODULE_fs__["default"];
const env = (null == deps ? void 0 : deps.env) ?? process.env;
const envPath = env.CHROME_FOR_TESTING_PATH || env.CHROMIUM_BINARY || env.CHROME_BINARY;
if (envPath && f.existsSync(envPath)) return envPath;
const prefixes = [
env.LOCALAPPDATA,
env.PROGRAMFILES,
env['PROGRAMFILES(X86)']
].filter(Boolean);
const suffixesAll = [
'\\Google\\Chrome for Testing\\Application\\chrome.exe',
'\\Google\\Chrome\\Application\\chrome.exe',
'\\Google\\Chrome Beta\\Application\\chrome.exe',
'\\Google\\Chrome Dev\\Application\\chrome.exe',
'\\Google\\Chrome SxS\\Application\\chrome.exe',
'\\Chromium\\Application\\chrome.exe'
];
const suffixes = allowFallback ? suffixesAll : [
suffixesAll[0]
];
for (const prefix of prefixes)for (const suffix of suffixes){
const exe = __WEBPACK_EXTERNAL_MODULE_node_path_c5b9b54f__["default"].join(prefix, suffix);
if (f.existsSync(exe)) return exe;
}
return null;
}
function scanUnknownPlatform(allowFallback = false, deps) {
const w = (null == deps ? void 0 : deps.which) ?? __WEBPACK_EXTERNAL_MODULE_which__["default"];
const rawEnv = [
process.env.CHROME_FOR_TESTING_PATH,
process.env.CHROMIUM_BINARY,
process.env.CHROME_BINARY
];
const envPath = rawEnv.find((v)=>{
if (!v) return false;
const s = String(v).trim().toLowerCase();
return s.length > 0 && 'undefined' !== s && 'null' !== s;
});
if (envPath) {
try {
const maybeCmd = w.sync(envPath);
if (maybeCmd) return maybeCmd;
} catch (_) {}
return envPath;
}
const stable = [
'google-chrome'
];
const fallbacks = [
'google-chrome-for-testing',
'chrome-for-testing',
'google-chrome-beta',
'google-chrome-unstable',
'chromium-browser',
'chromium'
];
const candidates = allowFallback ? [
...stable,
...fallbacks
] : stable;
for (const cmd of candidates)try {
const resolved = w.sync(cmd);
if (resolved) return resolved;
} catch (_) {}
return null;
}
function resolveFromPuppeteerCache(deps) {
const f = (null == deps ? void 0 : deps.fs) ?? __WEBPACK_EXTERNAL_MODULE_node_fs_5ea92f0c__["default"];
const env = (null == deps ? void 0 : deps.env) ?? process.env;
const platform = (null == deps ? void 0 : deps.platform) ?? process.platform;
try {
if ('darwin' === platform) {
const home = (null == deps ? void 0 : deps.homeDir) ?? env.HOME ?? '';
const bases = [];
if (home) bases.push(__WEBPACK_EXTERNAL_MODULE_node_path_c5b9b54f__["default"].join(home, 'Library', 'Caches', 'puppeteer', 'chrome'));
if (env.PUPPETEER_CACHE_DIR) bases.push(env.PUPPETEER_CACHE_DIR);
bases.push(__WEBPACK_EXTERNAL_MODULE_node_path_c5b9b54f__["default"].join(process.cwd(), 'chrome'));
bases.push(__WEBPACK_EXTERNAL_MODULE_node_path_c5b9b54f__["default"].join(process.cwd(), 'dist', 'extension-js', 'chrome-binary'));
for (const base of bases){
const dirs = listDirs(f, base).filter((d)=>d.startsWith('mac-') || d.startsWith('mac_arm-') || d.startsWith('mac-arm'));
const candidates = [];
for (const d of dirs){
candidates.push(__WEBPACK_EXTERNAL_MODULE_node_path_c5b9b54f__["default"].join(base, d, 'chrome-mac', 'Google Chrome for Testing.app', 'Contents', 'MacOS', 'Google Chrome for Testing'));
candidates.push(__WEBPACK_EXTERNAL_MODULE_node_path_c5b9b54f__["default"].join(base, d, 'chrome-mac-arm64', 'Google Chrome for Testing.app', 'Contents', 'MacOS', 'Google Chrome for Testing'));
candidates.push(__WEBPACK_EXTERNAL_MODULE_node_path_c5b9b54f__["default"].join(base, d, 'Google Chrome for Testing.app', 'Contents', 'MacOS', 'Google Chrome for Testing'));
}
const hit = firstExisting(f, candidates);
if (hit) return hit;
}
return null;
}
if ('win32' === platform) {
const lad = (null == deps ? void 0 : deps.localAppData) ?? env.LOCALAPPDATA;
if (!lad) return null;
const base = __WEBPACK_EXTERNAL_MODULE_node_path_c5b9b54f__["default"].join(lad, 'puppeteer', 'chrome');
const dirs = listDirs(f, base);
const ordered = [
...dirs.filter((d)=>d.startsWith('win64-')),
...dirs.filter((d)=>d.startsWith('win32-'))
];
const candidates = [];
for (const d of ordered){
candidates.push(__WEBPACK_EXTERNAL_MODULE_node_path_c5b9b54f__["default"].join(base, d, 'chrome-win64', 'chrome.exe'));
candidates.push(__WEBPACK_EXTERNAL_MODULE_node_path_c5b9b54f__["default"].join(base, d, 'chrome-win32', 'chrome.exe'));
candidates.push(__WEBPACK_EXTERNAL_MODULE_node_path_c5b9b54f__["default"].join(base, d, 'chrome.exe'));
}
return firstExisting(f, candidates);
}
const xdg = env.XDG_CACHE_HOME;
const home = (null == deps ? void 0 : deps.homeDir) ?? env.HOME ?? '';
const cacheBase = xdg || (home ? __WEBPACK_EXTERNAL_MODULE_node_path_c5b9b54f__["default"].join(home, '.cache') : void 0);
const bases = [
...cacheBase ? [
__WEBPACK_EXTERNAL_MODULE_node_path_c5b9b54f__["default"].join(cacheBase, 'puppeteer', 'chrome')
] : [],
env.PUPPETEER_CACHE_DIR || '',
__WEBPACK_EXTERNAL_MODULE_node_path_c5b9b54f__["default"].join(process.cwd(), 'chrome'),
__WEBPACK_EXTERNAL_MODULE_node_path_c5b9b54f__["default"].join(process.cwd(), 'dist', 'extension-js', 'chrome-binary')
].filter(Boolean);
for (const base of bases){
const dirs = listDirs(f, base).filter((d)=>d.startsWith('linux-'));
const candidates = [];
for (const d of dirs){
candidates.push(__WEBPACK_EXTERNAL_MODULE_node_path_c5b9b54f__["default"].join(base, d, 'chrome-linux64', 'chrome'));
candidates.push(__WEBPACK_EXTERNAL_MODULE_node_path_c5b9b54f__["default"].join(base, d, 'chrome-linux', 'chrome'));
candidates.push(__WEBPACK_EXTERNAL_MODULE_node_path_c5b9b54f__["default"].join(base, d, 'chrome'));
}
const hit = firstExisting(f, candidates);
if (hit) return hit;
}
return null;
} catch {
return null;
}
}
function listDirs(f, dir) {
try {
return f.readdirSync(dir, {
withFileTypes: true
}).filter((e)=>{
if (!e) return false;
const v = e.isDirectory;
return 'function' == typeof v ? v.call(e) : Boolean(v);
}).map((e)=>e.name || String(e));
} catch {
return [];
}
}
function firstExisting(f, candidates) {
for (const c of candidates)try {
if (c && f.existsSync(c)) return c;
} catch {}
return null;
}
function locateChrome(allowFallbackOrDeps, depsMaybe) {
const isBoolean = 'boolean' == typeof allowFallbackOrDeps;
const allowFallback = isBoolean ? allowFallbackOrDeps : false;
const deps = isBoolean ? depsMaybe : allowFallbackOrDeps;
const f = (null == deps ? void 0 : deps.fs) ?? __WEBPACK_EXTERNAL_MODULE_node_fs_5ea92f0c__["default"];
const e = (null == deps ? void 0 : deps.env) ?? process.env;
const platform = (null == deps ? void 0 : deps.platform) ?? process.platform;
let found = null;
switch(platform){
case 'darwin':
found = scanOsxPath(allowFallback, {
fs: f,
userhome: null == deps ? void 0 : deps.userhome
});
break;
case 'win32':
found = scanWindowsPath(allowFallback, {
fs: f,
env: e
});
break;
default:
found = scanUnknownPlatform(allowFallback, {
which: null == deps ? void 0 : deps.which
});
break;
}
if (!found) found = resolveFromPuppeteerCache({
fs: f,
env: e,
platform
});
const isTestEnv = (null == e ? void 0 : e.NODE_ENV) === 'test' || void 0 !== (null == e ? void 0 : e.VITEST) || void 0 !== (null == e ? void 0 : e.JEST_WORKER_ID);
const skipCliProbe = isTestEnv && 'darwin' === platform;
if (!found && !skipCliProbe) found = resolveFromPuppeteerBrowsersCLI();
return found;
}
function getInstallGuidance() {
return "We couldn't find a Chrome/Chromium browser on this machine.\n\nHere's the fastest way to get set up:\n\n1) Install Chrome for Testing (recommended)\n npx @puppeteer/browsers install chrome@stable\n\nThen re-run your command — we'll detect it automatically.\n\nAlternatively, install Chromium via your system's package manager and re-run.";
}
function locateChromeOrExplain(options) {
const allowFallback = 'boolean' == typeof options ? options : Boolean(null == options ? void 0 : options.allowFallback);
const found = locateChrome(allowFallback) || locateChrome(true);
if ('string' == typeof found && found) return found;
throw new Error(getInstallGuidance());
}
function getChromeVersion(bin, opts) {
const fromPptr = extractVersionFromPuppeteerPath(bin);
if (fromPptr) return fromPptr;
if ('win32' === process.platform) {
try {
const psPath = bin.replace(/'/g, "''");
const pv = (0, __WEBPACK_EXTERNAL_MODULE_child_process__.execFileSync)('powershell.exe', [
'-NoProfile',
'-Command',
`(Get-Item -LiteralPath '${psPath}').VersionInfo.ProductVersion`
], {
encoding: 'utf8',
stdio: [
'ignore',
'pipe',
'ignore'
]
}).trim();
return normalizeVersion(pv);
} catch {}
if (null == opts ? void 0 : opts.allowExec) {
const v = tryExec(bin, [
'--product-version'
]) || tryExec(bin, [
'--version'
]);
return normalizeVersion(v);
}
return null;
}
if ('darwin' === process.platform) {
try {
const contentsDir = __WEBPACK_EXTERNAL_MODULE_node_path_c5b9b54f__["default"].dirname(__WEBPACK_EXTERNAL_MODULE_node_path_c5b9b54f__["default"].dirname(bin));
const infoPlist = __WEBPACK_EXTERNAL_MODULE_node_path_c5b9b54f__["default"].join(contentsDir, 'Info.plist');
if (__WEBPACK_EXTERNAL_MODULE_node_fs_5ea92f0c__["default"].existsSync(infoPlist)) {
const xml = __WEBPACK_EXTERNAL_MODULE_node_fs_5ea92f0c__["default"].readFileSync(infoPlist, 'utf8');
const v = parsePlistString(xml, 'CFBundleShortVersionString') || parsePlistString(xml, 'CFBundleVersion') || '';
return normalizeVersion(v);
}
} catch {}
if (null == opts ? void 0 : opts.allowExec) {
const v = tryExec(bin, [
'--version'
]);
return normalizeVersion(v);
}
return null;
}
if (null == opts ? void 0 : opts.allowExec) {
const v = tryExec(bin, [
'--version'
]);
return normalizeVersion(v);
}
return null;
}
function extractVersionFromPuppeteerPath(p) {
const m = p.match(/[\\/]puppeteer[\\/]chrome[\\/](?:mac(?:_arm)?|win(?:32|64)|linux)-(\d+(?:\.\d+)*)(?:[\\/]|$)/i);
return m ? normalizeVersion(m[1]) : null;
}
function normalizeVersion(s) {
if (!s) return null;
const m = String(s).match(/(\d+(?:\.\d+){1,3})/);
return m ? m[1] : null;
}
function parsePlistString(xml, key) {
const re = new RegExp(`<key>${key}<\\/key>\\s*<string>([^<]+)<\\/string>`);
const m = xml.match(re);
return m ? m[1].trim() : null;
}
function tryExec(bin, args) {
try {
return (0, __WEBPACK_EXTERNAL_MODULE_child_process__.execFileSync)(bin, args, {
encoding: 'utf8',
stdio: [
'ignore',
'pipe',
'ignore'
]
}).trim();
} catch {
return null;
}
}
function resolveFromPuppeteerBrowsersCLI() {
const attempts = [
{
cmd: 'npx',
args: [
'-y',
'@puppeteer/browsers',
'path',
'chrome@stable'
]
},
{
cmd: 'pnpm',
args: [
'dlx',
'@puppeteer/browsers',
'path',
'chrome@stable'
]
},
{
cmd: 'yarn',
args: [
'dlx',
'@puppeteer/browsers',
'path',
'chrome@stable'
]
},
{
cmd: 'bunx',
args: [
'@puppeteer/browsers',
'path',
'chrome@stable'
]
}
];
for (const { cmd, args } of attempts)try {
const out = (0, __WEBPACK_EXTERNAL_MODULE_child_process__.execFileSync)(cmd, args, {
encoding: 'utf8',
stdio: [
'ignore',
'pipe',
'ignore'
],
timeout: 2000
}).trim();
if (out && __WEBPACK_EXTERNAL_MODULE_node_fs_5ea92f0c__["default"].existsSync(out)) return out;
} catch {}
return null;
}
export { locateChrome as default, getChromeVersion, getInstallGuidance, locateChromeOrExplain };