This commit is contained in:
2023-03-07 10:52:05 +07:00
commit 772f105c65
1032 changed files with 260918 additions and 0 deletions

View File

@@ -0,0 +1,51 @@
const { execSync } = require('child_process');
const path = require('path').posix;
const { canAccess, newLineRegex, sort } = require('./util');
function darwin(includeChromium = false) {
const suffixes = [
// '/Contents/MacOS/Google Chrome Canary',
'/Contents/MacOS/Google Chrome',
... includeChromium ? ['/Contents/MacOS/Chromium'] : []
];
const LSREGISTER = '/System/Library/Frameworks/CoreServices.framework' +
'/Versions/A/Frameworks/LaunchServices.framework' +
'/Versions/A/Support/lsregister';
const installations = [];
execSync(
`${LSREGISTER} -dump` +
' | grep -E -i \'(google chrome( canary)?' + (includeChromium ? '|chromium' : '') + ').app(\\s\\(0x[0-9a-f]+\\))?$\'' +
' | awk \'sub(/\\(0x[0-9a-f]+\\)/, "")\'' +
' | awk \'{$1=""; print $0}\'' +
' | awk \'{ gsub(/^[ \\t]+|[ \\t]+$/, ""); print }\'')
.toString()
.split(newLineRegex)
.forEach((inst) => {
suffixes.forEach(suffix => {
const execPath = path.join(inst.trim(), suffix);
if (canAccess(execPath)) {
installations.push(execPath);
}
});
});
// Retains one per line to maintain readability.
const priorities = [
{ regex: new RegExp(`^${process.env.HOME}/Applications/.*Chromium.app`), weight: 49 },
{ regex: new RegExp(`^${process.env.HOME}/Applications/.*Chrome.app`), weight: 50 },
// { regex: new RegExp(`^${process.env.HOME}/Applications/.*Chrome Canary.app`), weight: 51 },
{ regex: /^\/Applications\/.*Chromium.app/, weight: 99 },
{ regex: /^\/Applications\/.*Chrome.app/, weight: 100 },
// { regex: /^\/Applications\/.*Chrome Canary.app/, weight: 101 },
{ regex: /^\/Volumes\/.*Chromium.app/, weight: -3 },
{ regex: /^\/Volumes\/.*Chrome.app/, weight: -2 },
// { regex: /^\/Volumes\/.*Chrome Canary.app/, weight: -1 }
];
return sort(installations, priorities);
}
module.exports = darwin;

View File

@@ -0,0 +1,9 @@
/**
* find a executable chrome for all support system
* @returns {string} executable chrome full path
* @throws
* if no executable chrome find, ERROR_NO_INSTALLATIONS_FOUND will be throw
* if platform is not one if ['win32','darwin','linux'], ERROR_PLATFORM_NOT_SUPPORT will be throw
*/
declare function findChrome(): string;
export = findChrome;

View File

@@ -0,0 +1,39 @@
'use strict';
const ERROR_PLATFORM_NOT_SUPPORT = new Error('platform not support');
const ERROR_NO_INSTALLATIONS_FOUND = new Error('no chrome installations found');
/**
* Find a executable Chrome (or Chromium) for all supported systems.
*
* Supports macOS, Linux, and Windows.
*
* @param {boolean} includeChromium true if we should consider Chromium in our search, false otherwise.
* @returns {string} the first full path to an executable Chrome (or Chromium)
* @throws
* if no executable Chrome (or Chromium) find, ERROR_NO_INSTALLATIONS_FOUND will be throw
* if platform is not one if ['win32','darwin','linux'], ERROR_PLATFORM_NOT_SUPPORT will be throw
*/
function findChrome(includeChromium = false) {
const { platform } = process;
let installations = [];
switch (platform) {
case 'win32':
installations = require('./win32')(includeChromium);
break;
case 'darwin':
installations = require('./darwin')(includeChromium);
break;
case 'linux':
installations = require('./linux')(includeChromium);
break;
default:
throw ERROR_PLATFORM_NOT_SUPPORT;
}
if (installations.length) {
return installations[0];
} else {
throw ERROR_NO_INSTALLATIONS_FOUND;
}
}
module.exports = findChrome;

View File

@@ -0,0 +1,112 @@
const { execSync, execFileSync } = require('child_process');
const path = require('path').posix;
const fs = require('fs');
const { canAccess, sort, isExecutable, newLineRegex } = require('./util');
function findChromeExecutablesForLinuxDesktop(folder, includeChromium = false) {
const argumentsRegex = /(^[^ ]+).*/; // Take everything up to the first space
const chromeExecRegex = '^Exec=\/.*\/(google|chrome' + (includeChromium ? '|chromium' : '') + ')-.*';
let installations = [];
if (canAccess(folder)) {
// Output of the grep & print looks like:
// /opt/google/chrome/google-chrome --profile-directory
// /home/user/Downloads/chrome-linux/chrome-wrapper %U
let execPaths;
execPaths = execSync(`find "${folder}" -type f -exec grep -E "${chromeExecRegex}" "{}" \\; | awk -F '=' '{print $2}'`);
execPaths = execPaths
.toString()
.split(newLineRegex)
.map((execPath) => execPath.replace(argumentsRegex, '$1'));
execPaths.forEach((execPath) => canAccess(execPath) && installations.push(execPath));
}
return installations;
}
function findChromeExecutablesForLinux(validChromePaths, includeChromium = false) {
const executables = [
'google-chrome-stable',
'google-chrome',
... includeChromium ? ['chromium', 'chromium-browser', 'chromium/chrome'] : [] // chromium/chrome is for toradex machines where "chromium" is a directory. seen on Angstrom v2016.12
];
return executables.map(executable => {
const existingPaths = validChromePaths.map(possiblePath => {
try {
const chromePathToTest = possiblePath + '/' + executable;
if (fs.existsSync(chromePathToTest) && canAccess(chromePathToTest) && isExecutable(chromePathToTest)) {
return [ chromePathToTest ];
}
} catch (err) {
// not installed on this path or inaccessible
}
return [];
}).reduce((acc, val) => acc.concat(val), []); //.filter((foundChromePath) => foundChromePath);
// skip asking "which" command if the binary was found by searching the known paths.
if (existingPaths && existingPaths.length > 0) {
return existingPaths;
}
try {
const chromePath = execFileSync('which', [executable]).toString().split(newLineRegex)[0];
if (canAccess(chromePath)) {
return [ chromePath ];
}
} catch (err) {
// cmd which not installed.
}
return [];
}).reduce((acc, val) => acc.concat(val), []);
}
/**
* Look for linux executables in 2 ways
* 1. Look into the directories where .desktop are saved on gnome based distro's
* 2. Look for google-chrome-stable and google-chrome executables by using the which command
* If includeChromium is set, also look for chromium, chromium-browser, and chromium/chrome executables by using the which command
*/
function linux(includeChromium = false) {
let installations = [];
// 1. Look into the directories where .desktop are saved on gnome based distro's
const desktopInstallationFolders = [
path.join(require('os').homedir(), '.local/share/applications/'),
'/usr/share/applications/',
];
desktopInstallationFolders.forEach(folder => {
installations = installations.concat(findChromeExecutablesForLinuxDesktop(folder, includeChromium));
});
// 2. Look for google-chrome-stable and google-chrome (and optionally chromium, chromium-browser, and chromium-chrome) executables by using the which command
// see http://tldp.org/LDP/Linux-Filesystem-Hierarchy/html/
const validChromePaths = [
'/usr/bin',
'/usr/local/bin',
'/usr/sbin',
'/usr/local/sbin',
'/opt/bin',
'/usr/bin/X11',
'/usr/X11R6/bin'
];
installations = installations.concat(findChromeExecutablesForLinux(validChromePaths, includeChromium));
const priorities = [
{ regex: /chromium$/, weight: 52 },
{ regex: /chrome-wrapper$/, weight: 51 },
{ regex: /google-chrome-stable$/, weight: 50 },
{ regex: /google-chrome$/, weight: 49 },
{ regex: /chromium-browser$/, weight: 48 },
{ regex: /chrome$/, weight: 47 },
];
return sort(Array.from(new Set(installations.filter(Boolean))), priorities);
}
module.exports = linux;

View File

@@ -0,0 +1,56 @@
const fs = require('fs');
const newLineRegex = /\r?\n/;
function sort(installations, priorities) {
const defaultPriority = 10;
// assign priorities
return installations
.map((inst) => {
for (const pair of priorities) {
if (pair.regex.test(inst)) {
return { path: inst, weight: pair.weight };
}
}
return { path: inst, weight: defaultPriority };
})
// sort based on priorities
.sort((a, b) => (b.weight - a.weight))
// remove priority flag
.map(pair => pair.path);
}
function canAccess(file) {
if (!file) {
return false;
}
try {
fs.accessSync(file);
return true;
} catch (e) {
return false;
}
}
function isExecutable(file) {
if (!file) {
return false;
}
try {
var stat = fs.statSync(file);
return stat && typeof stat.isFile === "function" && stat.isFile();
} catch (e) {
return false;
}
}
module.exports = {
sort,
canAccess,
isExecutable,
newLineRegex,
}

View File

@@ -0,0 +1,30 @@
const path = require('path').win32;
const { canAccess } = require('./util');
const procesEnv = process.env;
function win32(includeChromium = false) {
const installations = [];
const suffixes = [
'\\Google\\Chrome SxS\\Application\\chrome.exe',
'\\Google\\Chrome\\Application\\chrome.exe',
'\\chrome-win32\\chrome.exe',
... includeChromium ? ['\\Chromium\\Application\\chrome.exe'] : [],
// '\\Google\\Chrome Beta\\Application\\chrome.exe',
];
const prefixes = [
procesEnv.LOCALAPPDATA,
procesEnv.PROGRAMFILES,
procesEnv['PROGRAMFILES(X86)']
].filter(prefix => prefix); // filter out undefined
prefixes.forEach(prefix => suffixes.forEach(suffix => {
const chromePath = path.join(prefix, suffix);
if (canAccess(chromePath)) {
installations.push(chromePath);
}
}));
return installations;
}
module.exports = win32;