@@ -71,6 +71,19 @@ object WebViewBootstrap {
7171
7272 if (! started.compareAndSet(false , true )) return
7373
74+ runCatching {
75+ installDir.parentFile?.mkdirs()
76+ if (! installDir.exists()) installDir.mkdirs()
77+ if (! cacheDir.exists()) cacheDir.mkdirs()
78+ }.onFailure { t ->
79+ logger.w(t) { " Failed to create KCEF directories: installDir=${installDir.absolutePath} , cacheDir=${cacheDir.absolutePath} " }
80+ }
81+
82+ logger.i {
83+ val resourcesDir = System .getProperty(" compose.application.resources.dir" ) ? : " (null)"
84+ " KCEF bootstrap starting. version=${BuildConfig .VERSION_NAME } , installDir=${installDir.absolutePath} , cacheDir=${cacheDir.absolutePath} , resourcesDir=$resourcesDir "
85+ }
86+
7487 val currentVersion = BuildConfig .VERSION_NAME
7588
7689 var isKcefInitialized = AppSettingsStore .kcefInitialized &&
@@ -183,6 +196,13 @@ object WebViewBootstrap {
183196 initError.value = preflightError
184197 return
185198 }
199+ logger.i(" 2.KCEF install directory is complete: ${installDir.absolutePath} " )
200+
201+ val os = System .getProperty(" os.name" ).lowercase()
202+ if (os.contains(" win" )) {
203+ val files = installDir.listFiles()?.map { it.name } ? : emptyList()
204+ logger.i(" KCEF install directory files: $files " )
205+ }
186206
187207 val initFailure = runCatching {
188208 withContext(awtDispatcher) {
@@ -192,6 +212,8 @@ object WebViewBootstrap {
192212 settings {
193213 cachePath = cacheDir.absolutePath
194214 logFile = kcefLog.absolutePath
215+ resourcesDirPath = installDir.absolutePath
216+ localesDirPath = File (installDir, " locales" ).absolutePath
195217 }
196218 progress {
197219 onInitialized {
@@ -233,10 +255,26 @@ object WebViewBootstrap {
233255 start(lastInstallDir!! , lastCacheDir!! , lastLogDir!! )
234256 }
235257
258+ private fun addLibraryDir (libraryPath : String ) {
259+ try {
260+ val field = ClassLoader ::class .java.getDeclaredField(" usr_paths" )
261+ field.isAccessible = true
262+ val paths = field.get(null ) as Array <String >
263+ if (paths.contains(libraryPath)) return
264+ val newPaths = paths.copyOf(paths.size + 1 )
265+ newPaths[paths.size] = libraryPath
266+ field.set(null , newPaths)
267+ logger.i { " Added to java.library.path: $libraryPath " }
268+ } catch (t: Throwable ) {
269+ logger.w(t) { " Failed to add library path: $libraryPath " }
270+ }
271+ }
272+
236273 private fun extractBundledKcef (targetInstallDir : File ) {
237274 if (! targetInstallDir.exists()) targetInstallDir.mkdirs()
238275
239276 if (extractBundledKcefFromResourcesDir(targetInstallDir)) return
277+ if (extractBundledKcefFromClasspathDirs(targetInstallDir)) return
240278 if (extractBundledKcefFromClasspathJar(targetInstallDir)) return
241279
242280 logger.w { " Bundled KCEF directory not found in resources dir or classpath, skipping extraction" }
@@ -248,7 +286,35 @@ object WebViewBootstrap {
248286 val bundledDir = File (resourcesDir, " kcef-bundle" )
249287 if (! bundledDir.exists() || ! bundledDir.isDirectory) return false
250288
251- logger.i { " Extracting bundled KCEF from resources dir: ${bundledDir.absolutePath} -> ${targetInstallDir.absolutePath} " }
289+ return copyBundledDir(
290+ bundledDir = bundledDir,
291+ targetInstallDir = targetInstallDir,
292+ sourceLabel = " resources dir"
293+ )
294+ }
295+
296+ private fun extractBundledKcefFromClasspathDirs (targetInstallDir : File ): Boolean {
297+ val classPath = System .getProperty(" java.class.path" )?.takeIf { it.isNotBlank() } ? : return false
298+ val entries = classPath.split(File .pathSeparatorChar).map { it.trim() }.filter { it.isNotBlank() }
299+
300+ for (entry in entries) {
301+ val dir = File (entry)
302+ if (! dir.isDirectory) continue
303+
304+ val bundledDir = File (dir, " kcef-bundle" )
305+ if (! bundledDir.isDirectory) continue
306+
307+ return copyBundledDir(
308+ bundledDir = bundledDir,
309+ targetInstallDir = targetInstallDir,
310+ sourceLabel = " classpath dir"
311+ )
312+ }
313+ return false
314+ }
315+
316+ private fun copyBundledDir (bundledDir : File , targetInstallDir : File , sourceLabel : String ): Boolean {
317+ logger.i { " Extracting bundled KCEF from $sourceLabel : ${bundledDir.absolutePath} -> ${targetInstallDir.absolutePath} " }
252318
253319 val supportsPosix = FileSystems .getDefault().supportedFileAttributeViews().contains(" posix" )
254320 var fileCount = 0
@@ -318,6 +384,16 @@ object WebViewBootstrap {
318384 val localesDir = File (installDir, " locales" )
319385 val hasLocales = localesDir.isDirectory && localesDir.listFiles()?.any { it.isFile && it.name.endsWith(" .pak" ) } == true
320386 val hasIcu = File (installDir, " icudtl.dat" ).isFile
387+
388+ // Check for critical binaries on Windows
389+ val os = System .getProperty(" os.name" ).lowercase()
390+ if (os.contains(" win" )) {
391+ val hasLibCef = File (installDir, " libcef.dll" ).isFile
392+ val hasJcef = File (installDir, " jcef.dll" ).isFile
393+ val hasHelper = File (installDir, " jcef_helper.exe" ).isFile
394+ return hasLocales && hasIcu && hasLibCef && hasJcef && hasHelper
395+ }
396+
321397 return hasLocales && hasIcu
322398 }
323399
0 commit comments