Skip to content

Commit

Permalink
Make faster browser detection by asynchronization
Browse files Browse the repository at this point in the history
  • Loading branch information
yhatt committed Sep 22, 2024
1 parent d07ee91 commit d68aae3
Show file tree
Hide file tree
Showing 5 changed files with 127 additions and 97 deletions.
2 changes: 1 addition & 1 deletion src/browser/finder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ export const findBrowser = async (
preferredPath: await (async () => {
if (opts.preferredPath) {
const normalized = await normalizeDarwinAppPath(opts.preferredPath)
if (isExecutable(normalized)) return normalized
if (await isExecutable(normalized)) return normalized
}
return undefined
})(),
Expand Down
29 changes: 11 additions & 18 deletions src/browser/finders/chrome.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { error, CLIErrorCode } from '../../error'
import { ChromeBrowser } from '../browsers/chrome'
import { ChromeCdpBrowser } from '../browsers/chrome-cdp'
import type { BrowserFinder, BrowserFinderResult } from '../finder'
import { getPlatform, isExecutable, which } from './utils'
import { findExecutableBinary, getPlatform } from './utils'

const chrome = (path: string): BrowserFinderResult => ({
path,
Expand All @@ -19,7 +19,7 @@ export const chromeFinder: BrowserFinder = async ({ preferredPath } = {}) => {
if (preferredPath) return chrome(preferredPath)

const platform = await getPlatform()
const installation = (() => {
const installation = await (async () => {
switch (platform) {
case 'darwin':
return darwinFast()
Expand All @@ -32,7 +32,7 @@ export const chromeFinder: BrowserFinder = async ({ preferredPath } = {}) => {
case 'wsl1':
return wsl()[0]
}
return fallback()
return await fallback()
/* c8 ignore stop */
})()

Expand All @@ -41,18 +41,11 @@ export const chromeFinder: BrowserFinder = async ({ preferredPath } = {}) => {
error('Chrome browser could not be found.', CLIErrorCode.NOT_FOUND_BROWSER)
}

const fallbackExecutableNames = [
'google-chrome-stable',
'google-chrome',
'chrome', // FreeBSD Chromium
'chromium-browser',
'chromium',
] as const

const fallback = () => {
for (const executableName of fallbackExecutableNames) {
const executablePath = which(executableName)
if (executablePath && isExecutable(executablePath)) return executablePath
}
return undefined
}
const fallback = async () =>
await findExecutableBinary([
'google-chrome-stable',
'google-chrome',
'chrome', // FreeBSD Chromium
'chromium-browser',
'chromium',
])
33 changes: 15 additions & 18 deletions src/browser/finders/edge.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,32 +7,29 @@ import {
import { ChromeBrowser } from '../browsers/chrome'
import { ChromeCdpBrowser } from '../browsers/chrome-cdp'
import type { BrowserFinder, BrowserFinderResult } from '../finder'
import { getPlatform, isExecutable } from './utils'
import { findExecutable, getPlatform } from './utils'

const edge = (path: string): BrowserFinderResult => ({
path,
acceptedBrowsers: [ChromeBrowser, ChromeCdpBrowser],
})

const findExecutable = (paths: string[]): string | undefined =>
paths.find((p) => isExecutable(p))

export const edgeFinder: BrowserFinder = async ({ preferredPath } = {}) => {
if (preferredPath) return edge(preferredPath)

const platform = await getPlatform()
const installation = (() => {
const installation = await (async () => {
switch (platform) {
case 'darwin':
return edgeFinderDarwin()
return await edgeFinderDarwin()
case 'linux':
return edgeFinderLinux()
return await edgeFinderLinux()
case 'win32':
return edgeFinderWin32()
return await edgeFinderWin32()
// CI cannot test against WSL environment
/* c8 ignore start */
case 'wsl1':
return edgeFinderWSL1()
return await edgeFinderWSL1()
}
return undefined
/* c8 ignore stop */
Expand All @@ -43,31 +40,31 @@ export const edgeFinder: BrowserFinder = async ({ preferredPath } = {}) => {
error('Edge browser could not be found.', CLIErrorCode.NOT_FOUND_BROWSER)
}

const edgeFinderDarwin = () =>
findExecutable([
const edgeFinderDarwin = async () =>
await findExecutable([
'/Applications/Microsoft Edge Canary.app/Contents/MacOS/Microsoft Edge Canary',
'/Applications/Microsoft Edge Dev.app/Contents/MacOS/Microsoft Edge Dev',
'/Applications/Microsoft Edge Beta.app/Contents/MacOS/Microsoft Edge Beta',
'/Applications/Microsoft Edge.app/Contents/MacOS/Microsoft Edge',
])

const edgeFinderLinux = () =>
findExecutable([
const edgeFinderLinux = async () =>
await findExecutable([
'/opt/microsoft/msedge-canary/msedge',
'/opt/microsoft/msedge-dev/msedge',
'/opt/microsoft/msedge-beta/msedge',
'/opt/microsoft/msedge/msedge',
])

const edgeFinderWin32 = ({
const edgeFinderWin32 = async ({
programFiles = process.env.PROGRAMFILES,
programFilesX86 = process.env['PROGRAMFILES(X86)'],
localAppData = process.env.LOCALAPPDATA,
}: {
programFiles?: string
programFilesX86?: string
localAppData?: string
} = {}): string | undefined => {
} = {}): Promise<string | undefined> => {
const paths: string[] = []

for (const prefix of [programFiles, programFilesX86, localAppData]) {
Expand All @@ -81,13 +78,13 @@ const edgeFinderWin32 = ({
)
}

return findExecutable(paths)
return await findExecutable(paths)
}

const edgeFinderWSL1 = () => {
const edgeFinderWSL1 = async () => {
const localAppData = resolveWindowsEnvSync('LOCALAPPDATA')

return edgeFinderWin32({
return await edgeFinderWin32({
programFiles: '/mnt/c/Program Files',
programFilesX86: '/mnt/c/Program Files (x86)',
localAppData: localAppData ? resolveWSLPathToGuestSync(localAppData) : '',
Expand Down
60 changes: 26 additions & 34 deletions src/browser/finders/firefox.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,42 +2,39 @@ import path from 'node:path'
import { error, CLIErrorCode } from '../../error'
import { FirefoxBrowser } from '../browsers/firefox'
import type { BrowserFinder, BrowserFinderResult } from '../finder'
import { getPlatform, isExecutable, which } from './utils'
import { getPlatform, findExecutable, findExecutableBinary } from './utils'

const firefox = (path: string): BrowserFinderResult => ({
path,
acceptedBrowsers: [FirefoxBrowser],
})

const findExecutable = (paths: string[]): string | undefined =>
paths.find((p) => isExecutable(p))

export const firefoxFinder: BrowserFinder = async ({ preferredPath } = {}) => {
if (preferredPath) return firefox(preferredPath)

const platform = await getPlatform()
const installation = (() => {
const installation = await (async () => {
switch (platform) {
case 'darwin':
return firefoxFinderDarwin()
return await firefoxFinderDarwin()
case 'win32':
return firefoxFinderWin32()
return await firefoxFinderWin32()
// CI cannot test against WSL environment
/* c8 ignore start */
case 'wsl1':
return firefoxFinderWSL1()
return await firefoxFinderWSL1()
/* c8 ignore stop */
}
return firefoxFinderFallback()
return await firefoxFinderFallback()
})()

if (installation) return firefox(installation)

error('Firefox browser could not be found.', CLIErrorCode.NOT_FOUND_BROWSER)
}

const firefoxFinderDarwin = () =>
findExecutable([
const firefoxFinderDarwin = async () =>
await findExecutable([
'/Applications/Firefox Nightly.app/Contents/MacOS/firefox',
'/Applications/Firefox Developer Edition.app/Contents/MacOS/firefox',
'/Applications/Firefox.app/Contents/MacOS/firefox', // Firefox stable, ESR, and beta
Expand All @@ -57,7 +54,7 @@ const winPossibleDrives = () => {
return Array.from(possibleDriveSet).sort()
}

const firefoxFinderWin32 = () => {
const firefoxFinderWin32 = async () => {
const prefixes: string[] = []

for (const drive of winPossibleDrives()) {
Expand All @@ -70,7 +67,7 @@ const firefoxFinderWin32 = () => {
}
}

return findExecutable(
return await findExecutable(
prefixes.flatMap((prefix) => [
path.join(prefix, 'Nightly', 'firefox.exe'),
path.join(prefix, 'Firefox Nightly', 'firefox.exe'),
Expand All @@ -80,15 +77,15 @@ const firefoxFinderWin32 = () => {
)
}

const firefoxFinderWSL1 = () => {
const firefoxFinderWSL1 = async () => {
const prefixes: string[] = []

for (const drive of winPossibleDrives()) {
prefixes.push(`/mnt/${drive}/Program Files`)
prefixes.push(`/mnt/${drive}/Program Files (x86)`)
}

return findExecutable(
return await findExecutable(
prefixes.flatMap((prefix) => [
path.join(prefix, 'Nightly', 'firefox.exe'),
path.join(prefix, 'Firefox Nightly', 'firefox.exe'),
Expand All @@ -98,22 +95,17 @@ const firefoxFinderWSL1 = () => {
)
}

// In Linux, Firefox must have only an executable name `firefox` in every
// editions, but some packages may provide different executable names.
const fallbackExecutableNames = [
'firefox-nightly',
'firefox-developer-edition',
'firefox-developer',
'firefox-dev',
'firefox-beta',
'firefox',
'firefox-esr',
] as const

const firefoxFinderFallback = () => {
for (const executableName of fallbackExecutableNames) {
const executablePath = which(executableName)
if (executablePath && isExecutable(executablePath)) return executablePath
}
return undefined
}
const firefoxFinderFallback = async () =>
await findExecutableBinary(
// In Linux, Firefox must have only an executable name `firefox` in every
// editions, but some packages may provide different executable names.
[
'firefox-nightly',
'firefox-developer-edition',
'firefox-developer',
'firefox-dev',
'firefox-beta',
'firefox',
'firefox-esr',
]
)
Loading

0 comments on commit d68aae3

Please sign in to comment.