diff --git a/src/browser/chrome.test.ts b/src/browser/chrome.test.ts index 5fbeae69f..0e7ec8450 100644 --- a/src/browser/chrome.test.ts +++ b/src/browser/chrome.test.ts @@ -10,6 +10,7 @@ import { findChromeExecutableMac, findChromeExecutableWindows, isChromeReachable, + resolveBrowserExecutableForPlatform, stopClawdChrome, } from "./chrome.js"; import { @@ -185,6 +186,29 @@ describe("browser chrome helpers", () => { exists.mockRestore(); }); + it("resolves Windows executables without LOCALAPPDATA", () => { + vi.stubEnv("LOCALAPPDATA", ""); + vi.stubEnv("ProgramFiles", "C:\\Program Files"); + vi.stubEnv("ProgramFiles(x86)", "C:\\Program Files (x86)"); + const marker = path.win32.join( + "Program Files", + "Google", + "Chrome", + "Application", + "chrome.exe", + ); + const exists = vi + .spyOn(fs, "existsSync") + .mockImplementation((p) => String(p).includes(marker)); + const exe = resolveBrowserExecutableForPlatform( + {} as Parameters[0], + "win32", + ); + expect(exe?.kind).toBe("chrome"); + expect(exe?.path).toMatch(/chrome\.exe$/); + exists.mockRestore(); + }); + it("reports reachability based on /json/version", async () => { vi.stubGlobal( "fetch", diff --git a/src/browser/chrome.ts b/src/browser/chrome.ts index f8bf48eb2..b1398f648 100644 --- a/src/browser/chrome.ts +++ b/src/browser/chrome.ts @@ -41,6 +41,16 @@ function exists(filePath: string) { } } +function findFirstExecutable( + candidates: Array, +): BrowserExecutable | null { + for (const candidate of candidates) { + if (exists(candidate.path)) return candidate; + } + + return null; +} + export function findChromeExecutableMac(): BrowserExecutable | null { const candidates: Array = [ { @@ -78,11 +88,7 @@ export function findChromeExecutableMac(): BrowserExecutable | null { }, ]; - for (const candidate of candidates) { - if (exists(candidate.path)) return candidate; - } - - return null; + return findFirstExecutable(candidates); } export function findChromeExecutableLinux(): BrowserExecutable | null { @@ -95,11 +101,7 @@ export function findChromeExecutableLinux(): BrowserExecutable | null { { kind: "chrome", path: "/usr/bin/chrome" }, ]; - for (const candidate of candidates) { - if (exists(candidate.path)) return candidate; - } - - return null; + return findFirstExecutable(candidates); } export function findChromeExecutableWindows(): BrowserExecutable | null { @@ -165,15 +167,12 @@ export function findChromeExecutableWindows(): BrowserExecutable | null { ), }); - for (const candidate of candidates) { - if (exists(candidate.path)) return candidate; - } - - return null; + return findFirstExecutable(candidates); } -function resolveBrowserExecutable( +export function resolveBrowserExecutableForPlatform( resolved: ResolvedBrowserConfig, + platform: NodeJS.Platform, ): BrowserExecutable | null { if (resolved.executablePath) { if (!exists(resolved.executablePath)) { @@ -184,12 +183,18 @@ function resolveBrowserExecutable( return { kind: "custom", path: resolved.executablePath }; } - if (process.platform === "darwin") return findChromeExecutableMac(); - if (process.platform === "linux") return findChromeExecutableLinux(); - if (process.platform === "win32") return findChromeExecutableWindows(); + if (platform === "darwin") return findChromeExecutableMac(); + if (platform === "linux") return findChromeExecutableLinux(); + if (platform === "win32") return findChromeExecutableWindows(); return null; } +function resolveBrowserExecutable( + resolved: ResolvedBrowserConfig, +): BrowserExecutable | null { + return resolveBrowserExecutableForPlatform(resolved, process.platform); +} + export function resolveClawdUserDataDir( profileName = DEFAULT_CLAWD_BROWSER_PROFILE_NAME, ) {