@hera-al/browser-server 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +212 -0
  3. package/dist/config.d.ts +44 -0
  4. package/dist/config.js +74 -0
  5. package/dist/core/cdp.d.ts +124 -0
  6. package/dist/core/cdp.helpers.d.ts +14 -0
  7. package/dist/core/cdp.helpers.js +148 -0
  8. package/dist/core/cdp.js +309 -0
  9. package/dist/core/chrome.d.ts +21 -0
  10. package/dist/core/chrome.executables.d.ts +10 -0
  11. package/dist/core/chrome.executables.js +559 -0
  12. package/dist/core/chrome.js +257 -0
  13. package/dist/core/chrome.profile-decoration.d.ts +11 -0
  14. package/dist/core/chrome.profile-decoration.js +148 -0
  15. package/dist/core/constants.d.ts +9 -0
  16. package/dist/core/constants.js +9 -0
  17. package/dist/core/profiles.d.ts +31 -0
  18. package/dist/core/profiles.js +99 -0
  19. package/dist/core/target-id.d.ts +12 -0
  20. package/dist/core/target-id.js +21 -0
  21. package/dist/data-dir.d.ts +2 -0
  22. package/dist/data-dir.js +6 -0
  23. package/dist/logger.d.ts +16 -0
  24. package/dist/logger.js +125 -0
  25. package/dist/playwright/pw-role-snapshot.d.ts +32 -0
  26. package/dist/playwright/pw-role-snapshot.js +337 -0
  27. package/dist/playwright/pw-session.d.ts +119 -0
  28. package/dist/playwright/pw-session.js +530 -0
  29. package/dist/playwright/pw-tools-core.activity.d.ts +22 -0
  30. package/dist/playwright/pw-tools-core.activity.js +47 -0
  31. package/dist/playwright/pw-tools-core.d.ts +9 -0
  32. package/dist/playwright/pw-tools-core.downloads.d.ts +35 -0
  33. package/dist/playwright/pw-tools-core.downloads.js +186 -0
  34. package/dist/playwright/pw-tools-core.interactions.d.ts +104 -0
  35. package/dist/playwright/pw-tools-core.interactions.js +404 -0
  36. package/dist/playwright/pw-tools-core.js +9 -0
  37. package/dist/playwright/pw-tools-core.responses.d.ts +14 -0
  38. package/dist/playwright/pw-tools-core.responses.js +91 -0
  39. package/dist/playwright/pw-tools-core.shared.d.ts +7 -0
  40. package/dist/playwright/pw-tools-core.shared.js +50 -0
  41. package/dist/playwright/pw-tools-core.snapshot.d.ts +65 -0
  42. package/dist/playwright/pw-tools-core.snapshot.js +144 -0
  43. package/dist/playwright/pw-tools-core.state.d.ts +47 -0
  44. package/dist/playwright/pw-tools-core.state.js +154 -0
  45. package/dist/playwright/pw-tools-core.storage.d.ts +48 -0
  46. package/dist/playwright/pw-tools-core.storage.js +76 -0
  47. package/dist/playwright/pw-tools-core.trace.d.ts +13 -0
  48. package/dist/playwright/pw-tools-core.trace.js +26 -0
  49. package/dist/server/browser-context.d.ts +29 -0
  50. package/dist/server/browser-context.js +137 -0
  51. package/dist/server/browser-server.d.ts +7 -0
  52. package/dist/server/browser-server.js +49 -0
  53. package/dist/server/routes/act.d.ts +4 -0
  54. package/dist/server/routes/act.js +176 -0
  55. package/dist/server/routes/basic.d.ts +4 -0
  56. package/dist/server/routes/basic.js +36 -0
  57. package/dist/server/routes/index.d.ts +4 -0
  58. package/dist/server/routes/index.js +16 -0
  59. package/dist/server/routes/snapshot.d.ts +4 -0
  60. package/dist/server/routes/snapshot.js +143 -0
  61. package/dist/server/routes/storage.d.ts +4 -0
  62. package/dist/server/routes/storage.js +117 -0
  63. package/dist/server/routes/tabs.d.ts +4 -0
  64. package/dist/server/routes/tabs.js +51 -0
  65. package/dist/server/standalone.d.ts +9 -0
  66. package/dist/server/standalone.js +42 -0
  67. package/dist/utils.d.ts +18 -0
  68. package/dist/utils.js +58 -0
  69. package/package.json +66 -0
@@ -0,0 +1,559 @@
1
+ import { execFileSync } from "node:child_process";
2
+ import fs from "node:fs";
3
+ import os from "node:os";
4
+ import path from "node:path";
5
+ const CHROMIUM_BUNDLE_IDS = new Set([
6
+ "com.google.Chrome",
7
+ "com.google.Chrome.beta",
8
+ "com.google.Chrome.canary",
9
+ "com.google.Chrome.dev",
10
+ "com.brave.Browser",
11
+ "com.brave.Browser.beta",
12
+ "com.brave.Browser.nightly",
13
+ "com.microsoft.Edge",
14
+ "com.microsoft.EdgeBeta",
15
+ "com.microsoft.EdgeDev",
16
+ "com.microsoft.EdgeCanary",
17
+ "org.chromium.Chromium",
18
+ "com.vivaldi.Vivaldi",
19
+ "com.operasoftware.Opera",
20
+ "com.operasoftware.OperaGX",
21
+ "com.yandex.desktop.yandex-browser",
22
+ "company.thebrowser.Browser", // Arc
23
+ ]);
24
+ const CHROMIUM_DESKTOP_IDS = new Set([
25
+ "google-chrome.desktop",
26
+ "google-chrome-beta.desktop",
27
+ "google-chrome-unstable.desktop",
28
+ "brave-browser.desktop",
29
+ "microsoft-edge.desktop",
30
+ "microsoft-edge-beta.desktop",
31
+ "microsoft-edge-dev.desktop",
32
+ "microsoft-edge-canary.desktop",
33
+ "chromium.desktop",
34
+ "chromium-browser.desktop",
35
+ "vivaldi.desktop",
36
+ "vivaldi-stable.desktop",
37
+ "opera.desktop",
38
+ "opera-gx.desktop",
39
+ "yandex-browser.desktop",
40
+ "org.chromium.Chromium.desktop",
41
+ ]);
42
+ const CHROMIUM_EXE_NAMES = new Set([
43
+ "chrome.exe",
44
+ "msedge.exe",
45
+ "brave.exe",
46
+ "brave-browser.exe",
47
+ "chromium.exe",
48
+ "vivaldi.exe",
49
+ "opera.exe",
50
+ "launcher.exe",
51
+ "yandex.exe",
52
+ "yandexbrowser.exe",
53
+ // mac/linux names
54
+ "google chrome",
55
+ "google chrome canary",
56
+ "brave browser",
57
+ "microsoft edge",
58
+ "chromium",
59
+ "chrome",
60
+ "brave",
61
+ "msedge",
62
+ "brave-browser",
63
+ "google-chrome",
64
+ "google-chrome-stable",
65
+ "google-chrome-beta",
66
+ "google-chrome-unstable",
67
+ "microsoft-edge",
68
+ "microsoft-edge-beta",
69
+ "microsoft-edge-dev",
70
+ "microsoft-edge-canary",
71
+ "chromium-browser",
72
+ "vivaldi",
73
+ "vivaldi-stable",
74
+ "opera",
75
+ "opera-stable",
76
+ "opera-gx",
77
+ "yandex-browser",
78
+ ]);
79
+ function exists(filePath) {
80
+ try {
81
+ return fs.existsSync(filePath);
82
+ }
83
+ catch {
84
+ return false;
85
+ }
86
+ }
87
+ function execText(command, args, timeoutMs = 1200, maxBuffer = 1024 * 1024) {
88
+ try {
89
+ const output = execFileSync(command, args, {
90
+ timeout: timeoutMs,
91
+ encoding: "utf8",
92
+ maxBuffer,
93
+ });
94
+ return String(output ?? "").trim() || null;
95
+ }
96
+ catch {
97
+ return null;
98
+ }
99
+ }
100
+ function inferKindFromIdentifier(identifier) {
101
+ const id = identifier.toLowerCase();
102
+ if (id.includes("brave")) {
103
+ return "brave";
104
+ }
105
+ if (id.includes("edge")) {
106
+ return "edge";
107
+ }
108
+ if (id.includes("chromium")) {
109
+ return "chromium";
110
+ }
111
+ if (id.includes("canary")) {
112
+ return "canary";
113
+ }
114
+ if (id.includes("opera") ||
115
+ id.includes("vivaldi") ||
116
+ id.includes("yandex") ||
117
+ id.includes("thebrowser")) {
118
+ return "chromium";
119
+ }
120
+ return "chrome";
121
+ }
122
+ function inferKindFromExecutableName(name) {
123
+ const lower = name.toLowerCase();
124
+ if (lower.includes("brave")) {
125
+ return "brave";
126
+ }
127
+ if (lower.includes("edge") || lower.includes("msedge")) {
128
+ return "edge";
129
+ }
130
+ if (lower.includes("chromium")) {
131
+ return "chromium";
132
+ }
133
+ if (lower.includes("canary") || lower.includes("sxs")) {
134
+ return "canary";
135
+ }
136
+ if (lower.includes("opera") || lower.includes("vivaldi") || lower.includes("yandex")) {
137
+ return "chromium";
138
+ }
139
+ return "chrome";
140
+ }
141
+ function detectDefaultChromiumExecutable(platform) {
142
+ if (platform === "darwin") {
143
+ return detectDefaultChromiumExecutableMac();
144
+ }
145
+ if (platform === "linux") {
146
+ return detectDefaultChromiumExecutableLinux();
147
+ }
148
+ if (platform === "win32") {
149
+ return detectDefaultChromiumExecutableWindows();
150
+ }
151
+ return null;
152
+ }
153
+ function detectDefaultChromiumExecutableMac() {
154
+ const bundleId = detectDefaultBrowserBundleIdMac();
155
+ if (!bundleId || !CHROMIUM_BUNDLE_IDS.has(bundleId)) {
156
+ return null;
157
+ }
158
+ const appPathRaw = execText("/usr/bin/osascript", [
159
+ "-e",
160
+ `POSIX path of (path to application id "${bundleId}")`,
161
+ ]);
162
+ if (!appPathRaw) {
163
+ return null;
164
+ }
165
+ const appPath = appPathRaw.trim().replace(/\/$/, "");
166
+ const exeName = execText("/usr/bin/defaults", [
167
+ "read",
168
+ path.join(appPath, "Contents", "Info"),
169
+ "CFBundleExecutable",
170
+ ]);
171
+ if (!exeName) {
172
+ return null;
173
+ }
174
+ const exePath = path.join(appPath, "Contents", "MacOS", exeName.trim());
175
+ if (!exists(exePath)) {
176
+ return null;
177
+ }
178
+ return { kind: inferKindFromIdentifier(bundleId), path: exePath };
179
+ }
180
+ function detectDefaultBrowserBundleIdMac() {
181
+ const plistPath = path.join(os.homedir(), "Library/Preferences/com.apple.LaunchServices/com.apple.launchservices.secure.plist");
182
+ if (!exists(plistPath)) {
183
+ return null;
184
+ }
185
+ const handlersRaw = execText("/usr/bin/plutil", ["-extract", "LSHandlers", "json", "-o", "-", "--", plistPath], 2000, 5 * 1024 * 1024);
186
+ if (!handlersRaw) {
187
+ return null;
188
+ }
189
+ let handlers;
190
+ try {
191
+ handlers = JSON.parse(handlersRaw);
192
+ }
193
+ catch {
194
+ return null;
195
+ }
196
+ if (!Array.isArray(handlers)) {
197
+ return null;
198
+ }
199
+ const resolveScheme = (scheme) => {
200
+ let candidate = null;
201
+ for (const entry of handlers) {
202
+ if (!entry || typeof entry !== "object") {
203
+ continue;
204
+ }
205
+ const record = entry;
206
+ if (record.LSHandlerURLScheme !== scheme) {
207
+ continue;
208
+ }
209
+ const role = (typeof record.LSHandlerRoleAll === "string" && record.LSHandlerRoleAll) ||
210
+ (typeof record.LSHandlerRoleViewer === "string" && record.LSHandlerRoleViewer) ||
211
+ null;
212
+ if (role) {
213
+ candidate = role;
214
+ }
215
+ }
216
+ return candidate;
217
+ };
218
+ return resolveScheme("http") ?? resolveScheme("https");
219
+ }
220
+ function detectDefaultChromiumExecutableLinux() {
221
+ const desktopId = execText("xdg-settings", ["get", "default-web-browser"]) ||
222
+ execText("xdg-mime", ["query", "default", "x-scheme-handler/http"]);
223
+ if (!desktopId) {
224
+ return null;
225
+ }
226
+ const trimmed = desktopId.trim();
227
+ if (!CHROMIUM_DESKTOP_IDS.has(trimmed)) {
228
+ return null;
229
+ }
230
+ const desktopPath = findDesktopFilePath(trimmed);
231
+ if (!desktopPath) {
232
+ return null;
233
+ }
234
+ const execLine = readDesktopExecLine(desktopPath);
235
+ if (!execLine) {
236
+ return null;
237
+ }
238
+ const command = extractExecutableFromExecLine(execLine);
239
+ if (!command) {
240
+ return null;
241
+ }
242
+ const resolved = resolveLinuxExecutablePath(command);
243
+ if (!resolved) {
244
+ return null;
245
+ }
246
+ const exeName = path.posix.basename(resolved).toLowerCase();
247
+ if (!CHROMIUM_EXE_NAMES.has(exeName)) {
248
+ return null;
249
+ }
250
+ return { kind: inferKindFromExecutableName(exeName), path: resolved };
251
+ }
252
+ function detectDefaultChromiumExecutableWindows() {
253
+ const progId = readWindowsProgId();
254
+ const command = (progId ? readWindowsCommandForProgId(progId) : null) || readWindowsCommandForProgId("http");
255
+ if (!command) {
256
+ return null;
257
+ }
258
+ const expanded = expandWindowsEnvVars(command);
259
+ const exePath = extractWindowsExecutablePath(expanded);
260
+ if (!exePath) {
261
+ return null;
262
+ }
263
+ if (!exists(exePath)) {
264
+ return null;
265
+ }
266
+ const exeName = path.win32.basename(exePath).toLowerCase();
267
+ if (!CHROMIUM_EXE_NAMES.has(exeName)) {
268
+ return null;
269
+ }
270
+ return { kind: inferKindFromExecutableName(exeName), path: exePath };
271
+ }
272
+ function findDesktopFilePath(desktopId) {
273
+ const candidates = [
274
+ path.join(os.homedir(), ".local", "share", "applications", desktopId),
275
+ path.join("/usr/local/share/applications", desktopId),
276
+ path.join("/usr/share/applications", desktopId),
277
+ path.join("/var/lib/snapd/desktop/applications", desktopId),
278
+ ];
279
+ for (const candidate of candidates) {
280
+ if (exists(candidate)) {
281
+ return candidate;
282
+ }
283
+ }
284
+ return null;
285
+ }
286
+ function readDesktopExecLine(desktopPath) {
287
+ try {
288
+ const raw = fs.readFileSync(desktopPath, "utf8");
289
+ const lines = raw.split(/\r?\n/);
290
+ for (const line of lines) {
291
+ if (line.startsWith("Exec=")) {
292
+ return line.slice("Exec=".length).trim();
293
+ }
294
+ }
295
+ }
296
+ catch {
297
+ // ignore
298
+ }
299
+ return null;
300
+ }
301
+ function extractExecutableFromExecLine(execLine) {
302
+ const tokens = splitExecLine(execLine);
303
+ for (const token of tokens) {
304
+ if (!token) {
305
+ continue;
306
+ }
307
+ if (token === "env") {
308
+ continue;
309
+ }
310
+ if (token.includes("=") && !token.startsWith("/") && !token.includes("\\")) {
311
+ continue;
312
+ }
313
+ return token.replace(/^["']|["']$/g, "");
314
+ }
315
+ return null;
316
+ }
317
+ function splitExecLine(line) {
318
+ const tokens = [];
319
+ let current = "";
320
+ let inQuotes = false;
321
+ let quoteChar = "";
322
+ for (let i = 0; i < line.length; i += 1) {
323
+ const ch = line[i];
324
+ if ((ch === '"' || ch === "'") && (!inQuotes || ch === quoteChar)) {
325
+ if (inQuotes) {
326
+ inQuotes = false;
327
+ quoteChar = "";
328
+ }
329
+ else {
330
+ inQuotes = true;
331
+ quoteChar = ch;
332
+ }
333
+ continue;
334
+ }
335
+ if (!inQuotes && /\s/.test(ch)) {
336
+ if (current) {
337
+ tokens.push(current);
338
+ current = "";
339
+ }
340
+ continue;
341
+ }
342
+ current += ch;
343
+ }
344
+ if (current) {
345
+ tokens.push(current);
346
+ }
347
+ return tokens;
348
+ }
349
+ function resolveLinuxExecutablePath(command) {
350
+ const cleaned = command.trim().replace(/%[a-zA-Z]/g, "");
351
+ if (!cleaned) {
352
+ return null;
353
+ }
354
+ if (cleaned.startsWith("/")) {
355
+ return cleaned;
356
+ }
357
+ const resolved = execText("which", [cleaned], 800);
358
+ return resolved ? resolved.trim() : null;
359
+ }
360
+ function readWindowsProgId() {
361
+ const output = execText("reg", [
362
+ "query",
363
+ "HKCU\\Software\\Microsoft\\Windows\\Shell\\Associations\\UrlAssociations\\http\\UserChoice",
364
+ "/v",
365
+ "ProgId",
366
+ ]);
367
+ if (!output) {
368
+ return null;
369
+ }
370
+ const match = output.match(/ProgId\s+REG_\w+\s+(.+)$/im);
371
+ return match?.[1]?.trim() || null;
372
+ }
373
+ function readWindowsCommandForProgId(progId) {
374
+ const key = progId === "http"
375
+ ? "HKCR\\http\\shell\\open\\command"
376
+ : `HKCR\\${progId}\\shell\\open\\command`;
377
+ const output = execText("reg", ["query", key, "/ve"]);
378
+ if (!output) {
379
+ return null;
380
+ }
381
+ const match = output.match(/REG_\w+\s+(.+)$/im);
382
+ return match?.[1]?.trim() || null;
383
+ }
384
+ function expandWindowsEnvVars(value) {
385
+ return value.replace(/%([^%]+)%/g, (_match, name) => {
386
+ const key = String(name ?? "").trim();
387
+ return key ? (process.env[key] ?? `%${key}%`) : _match;
388
+ });
389
+ }
390
+ function extractWindowsExecutablePath(command) {
391
+ const quoted = command.match(/"([^"]+\\.exe)"/i);
392
+ if (quoted?.[1]) {
393
+ return quoted[1];
394
+ }
395
+ const unquoted = command.match(/([^\\s]+\\.exe)/i);
396
+ if (unquoted?.[1]) {
397
+ return unquoted[1];
398
+ }
399
+ return null;
400
+ }
401
+ function findFirstExecutable(candidates) {
402
+ for (const candidate of candidates) {
403
+ if (exists(candidate.path)) {
404
+ return candidate;
405
+ }
406
+ }
407
+ return null;
408
+ }
409
+ export function findChromeExecutableMac() {
410
+ const candidates = [
411
+ {
412
+ kind: "chrome",
413
+ path: "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome",
414
+ },
415
+ {
416
+ kind: "chrome",
417
+ path: path.join(os.homedir(), "Applications/Google Chrome.app/Contents/MacOS/Google Chrome"),
418
+ },
419
+ {
420
+ kind: "brave",
421
+ path: "/Applications/Brave Browser.app/Contents/MacOS/Brave Browser",
422
+ },
423
+ {
424
+ kind: "brave",
425
+ path: path.join(os.homedir(), "Applications/Brave Browser.app/Contents/MacOS/Brave Browser"),
426
+ },
427
+ {
428
+ kind: "edge",
429
+ path: "/Applications/Microsoft Edge.app/Contents/MacOS/Microsoft Edge",
430
+ },
431
+ {
432
+ kind: "edge",
433
+ path: path.join(os.homedir(), "Applications/Microsoft Edge.app/Contents/MacOS/Microsoft Edge"),
434
+ },
435
+ {
436
+ kind: "chromium",
437
+ path: "/Applications/Chromium.app/Contents/MacOS/Chromium",
438
+ },
439
+ {
440
+ kind: "chromium",
441
+ path: path.join(os.homedir(), "Applications/Chromium.app/Contents/MacOS/Chromium"),
442
+ },
443
+ {
444
+ kind: "canary",
445
+ path: "/Applications/Google Chrome Canary.app/Contents/MacOS/Google Chrome Canary",
446
+ },
447
+ {
448
+ kind: "canary",
449
+ path: path.join(os.homedir(), "Applications/Google Chrome Canary.app/Contents/MacOS/Google Chrome Canary"),
450
+ },
451
+ ];
452
+ return findFirstExecutable(candidates);
453
+ }
454
+ export function findChromeExecutableLinux() {
455
+ const candidates = [
456
+ { kind: "chrome", path: "/usr/bin/google-chrome" },
457
+ { kind: "chrome", path: "/usr/bin/google-chrome-stable" },
458
+ { kind: "chrome", path: "/usr/bin/chrome" },
459
+ { kind: "brave", path: "/usr/bin/brave-browser" },
460
+ { kind: "brave", path: "/usr/bin/brave-browser-stable" },
461
+ { kind: "brave", path: "/usr/bin/brave" },
462
+ { kind: "brave", path: "/snap/bin/brave" },
463
+ { kind: "edge", path: "/usr/bin/microsoft-edge" },
464
+ { kind: "edge", path: "/usr/bin/microsoft-edge-stable" },
465
+ { kind: "chromium", path: "/usr/bin/chromium" },
466
+ { kind: "chromium", path: "/usr/bin/chromium-browser" },
467
+ { kind: "chromium", path: "/snap/bin/chromium" },
468
+ ];
469
+ return findFirstExecutable(candidates);
470
+ }
471
+ export function findChromeExecutableWindows() {
472
+ const localAppData = process.env.LOCALAPPDATA ?? "";
473
+ const programFiles = process.env.ProgramFiles ?? "C:\\Program Files";
474
+ // Must use bracket notation: variable name contains parentheses
475
+ const programFilesX86 = process.env["ProgramFiles(x86)"] ?? "C:\\Program Files (x86)";
476
+ const joinWin = path.win32.join;
477
+ const candidates = [];
478
+ if (localAppData) {
479
+ // Chrome (user install)
480
+ candidates.push({
481
+ kind: "chrome",
482
+ path: joinWin(localAppData, "Google", "Chrome", "Application", "chrome.exe"),
483
+ });
484
+ // Brave (user install)
485
+ candidates.push({
486
+ kind: "brave",
487
+ path: joinWin(localAppData, "BraveSoftware", "Brave-Browser", "Application", "brave.exe"),
488
+ });
489
+ // Edge (user install)
490
+ candidates.push({
491
+ kind: "edge",
492
+ path: joinWin(localAppData, "Microsoft", "Edge", "Application", "msedge.exe"),
493
+ });
494
+ // Chromium (user install)
495
+ candidates.push({
496
+ kind: "chromium",
497
+ path: joinWin(localAppData, "Chromium", "Application", "chrome.exe"),
498
+ });
499
+ // Chrome Canary (user install)
500
+ candidates.push({
501
+ kind: "canary",
502
+ path: joinWin(localAppData, "Google", "Chrome SxS", "Application", "chrome.exe"),
503
+ });
504
+ }
505
+ // Chrome (system install, 64-bit)
506
+ candidates.push({
507
+ kind: "chrome",
508
+ path: joinWin(programFiles, "Google", "Chrome", "Application", "chrome.exe"),
509
+ });
510
+ // Chrome (system install, 32-bit on 64-bit Windows)
511
+ candidates.push({
512
+ kind: "chrome",
513
+ path: joinWin(programFilesX86, "Google", "Chrome", "Application", "chrome.exe"),
514
+ });
515
+ // Brave (system install, 64-bit)
516
+ candidates.push({
517
+ kind: "brave",
518
+ path: joinWin(programFiles, "BraveSoftware", "Brave-Browser", "Application", "brave.exe"),
519
+ });
520
+ // Brave (system install, 32-bit on 64-bit Windows)
521
+ candidates.push({
522
+ kind: "brave",
523
+ path: joinWin(programFilesX86, "BraveSoftware", "Brave-Browser", "Application", "brave.exe"),
524
+ });
525
+ // Edge (system install, 64-bit)
526
+ candidates.push({
527
+ kind: "edge",
528
+ path: joinWin(programFiles, "Microsoft", "Edge", "Application", "msedge.exe"),
529
+ });
530
+ // Edge (system install, 32-bit on 64-bit Windows)
531
+ candidates.push({
532
+ kind: "edge",
533
+ path: joinWin(programFilesX86, "Microsoft", "Edge", "Application", "msedge.exe"),
534
+ });
535
+ return findFirstExecutable(candidates);
536
+ }
537
+ export function resolveBrowserExecutableForPlatform(resolved, platform) {
538
+ if (resolved.executablePath) {
539
+ if (!exists(resolved.executablePath)) {
540
+ throw new Error(`browser.executablePath not found: ${resolved.executablePath}`);
541
+ }
542
+ return { kind: "custom", path: resolved.executablePath };
543
+ }
544
+ const detected = detectDefaultChromiumExecutable(platform);
545
+ if (detected) {
546
+ return detected;
547
+ }
548
+ if (platform === "darwin") {
549
+ return findChromeExecutableMac();
550
+ }
551
+ if (platform === "linux") {
552
+ return findChromeExecutableLinux();
553
+ }
554
+ if (platform === "win32") {
555
+ return findChromeExecutableWindows();
556
+ }
557
+ return null;
558
+ }
559
+ //# sourceMappingURL=chrome.executables.js.map