@@ -62,6 +62,79 @@ fun isGzipCompressed(data: ByteArray): Boolean {
6262 return header == listOf (0x1F , 0x8B )
6363}
6464
65+ /* *
66+ * Browser search configuration flags
67+ */
68+ data class BrowserSearchConfig (
69+ val searchInPath : Boolean = true ,
70+ val searchMacosApplications : Boolean = false ,
71+ val searchWindowsProgramFiles : Boolean = false ,
72+ val searchLinuxCommonPaths : Boolean = false ,
73+ )
74+
75+ /* *
76+ * Common helper to search for browser executables based on platform configuration.
77+ * @param config Platform-specific search configuration
78+ * @param pathSeparator The path separator character (":" for POSIX, ";" for Windows)
79+ * @param pathEnv The PATH environment variable value
80+ * @param executableNames List of executable names to search for (e.g., ["chrome", "google-chrome"])
81+ * @param macosAppPaths macOS .app bundle paths (only used if searchMacosApplications is true)
82+ * @param windowsProgramFilesSuffixes Windows Program Files subdirectories (only used if searchWindowsProgramFiles is true)
83+ * @param linuxCommonPaths Common Linux installation paths (only used if searchLinuxCommonPaths is true)
84+ * @param windowsExecutableNames Windows executable names with .exe extension
85+ * @param windowsProgramFilesGetter Callback to get Windows program files directories
86+ */
87+ internal fun findBrowserExecutableCommon (
88+ config : BrowserSearchConfig ,
89+ pathSeparator : String ,
90+ pathEnv : String? ,
91+ executableNames : List <String >,
92+ macosAppPaths : List <String > = emptyList(),
93+ windowsProgramFilesSuffixes : List <String > = emptyList(),
94+ windowsExecutableNames : List <String > = emptyList(),
95+ linuxCommonPaths : List <String > = emptyList(),
96+ windowsProgramFilesGetter : () -> List <String > = { emptyList() },
97+ ): Path ? {
98+ val candidates = mutableListOf<Path >()
99+
100+ // macOS applications
101+ if (config.searchMacosApplications) {
102+ candidates.addAll(macosAppPaths.map { Path (it) })
103+ }
104+
105+ // Windows Program Files
106+ if (config.searchWindowsProgramFiles) {
107+ val programFiles = windowsProgramFilesGetter()
108+ for (base in programFiles) {
109+ for (suffix in windowsProgramFilesSuffixes) {
110+ for (exe in windowsExecutableNames) {
111+ candidates.add(Path (" $base /$suffix /$exe " ))
112+ }
113+ }
114+ }
115+ }
116+
117+ // Linux common paths
118+ if (config.searchLinuxCommonPaths) {
119+ candidates.addAll(linuxCommonPaths.map { Path (it) })
120+ }
121+
122+ // Search in PATH
123+ if (config.searchInPath) {
124+ val paths = pathEnv?.split(pathSeparator) ? : emptyList()
125+ for (pathDir in paths) {
126+ for (exe in executableNames) {
127+ candidates.add(Path (" $pathDir /$exe " ))
128+ }
129+ }
130+ }
131+
132+ // Return the shortest path that exists
133+ return candidates
134+ .filter { exists(it) }
135+ .minByOrNull { it.toString().length }
136+ }
137+
65138expect abstract class Process {
66139 fun isAlive (): Boolean
67140 fun pid (): Long
@@ -74,6 +147,7 @@ expect fun isPosix(): Boolean
74147expect fun isRoot (): Boolean
75148expect fun tempProfileDir (): Path
76149expect fun exists (path : Path ): Boolean
150+ expect fun getEnv (name : String ): String?
77151expect fun findChromeExecutable (): Path ?
78152expect fun findOperaExecutable (): Path ?
79153expect fun findBraveExecutable (): Path ?
0 commit comments