chromiumembedded / java-cef

Java Chromium Embedded Framework (JCEF). A simple framework for embedding Chromium-based browsers in other applications using the Java programming language.
https://bitbucket.org/chromiumembedded/java-cef
Other
655 stars 147 forks source link

Linux/Mac: Fix discovery of icudtl.dat #109

Open magreenblatt opened 10 years ago

magreenblatt commented 10 years ago

Original report by Anonymous.


Original issue 109 created by christophe.cornu on 2014-08-15T18:35:40.000Z:

Congrats on the work for revision 99 with the adoption of CEF 3.1916.1749 and the Mac fix for visibility. For the first time we can have multiple tabs working on the Mac :-) I did notice a regression affecting those that launch their app through the java command line. Details below.

What steps will reproduce the problem?

  1. Get and build latest JCEF r99 on Mac
  2. Double click on jcef_app.app. All works fine.
  3. Start a Java program that uses jcef, from the command line (using e.g. /Library/Java/JavaVirtualMachines/jdk1.7.0_55.jdk/Contents/Home/bin/java)

What is the expected output? What do you see instead?

When starting the program from the command line with the java executable, Java_org_cef_CefApp_N_1Initialize fails with the following msg.

[0815/140948:FATAL:content_main_runner.cc(751)] Check failed: base::i18n::InitializeICU().

A bad workaround is to copy icudtl.dat from jcef_app.app/Contents/Frameworks/Resources/ to /Library/Java/JavaVirtualMachines/jdk1.7.0_55.jdk/Contents/Home/bin/java (or wherever your java executable is installed).

What do you recommend to have util_mac::CefInitializeOnMainThread find icudtl.dat in the right location instead of getting it from the main executable's path? pathToJavaDLL points to jcef_app.app/Contents/Java, we can build the full path pointing to jcef_app.app/Contents/Frameworks/Resources/. How can we tell CEF to use that location?

These 2 links are interesting.
http://www.magpcss.org/ceforum/viewtopic.php?f=6&t=11459https://code.google.com/p/chromiumembedded/issues/detail?id=1198

This was not a pb with former revisions (r90) when icudtl.dll was loaded as a dll directly.

magreenblatt commented 10 years ago

Original comment by Anonymous.


Comment 1. originally posted by christophe.cornu on 2014-08-18T14:11:12.000Z:

Looking at InitializeICU in icu_util.cc
https://chromium.googlesource.com/chromium/src/base/+/refs/heads/master/i18n/icu\_util.cc

The code uses the module_dir on Windows only. On Mac, it uses different logic. And this doesn't seem to be controllable by a property.

magreenblatt commented 10 years ago

Comment 2. originally posted by magreenblatt on 2014-08-20T15:10:23.000Z:

issue #110 has been merged into this issue.

magreenblatt commented 10 years ago

Comment 3. originally posted by magreenblatt on 2014-08-20T15:11:01.000Z:

magreenblatt commented 10 years ago

Original comment by Anonymous.


Comment 4. originally posted by anthapu on 2014-08-29T16:38:23.000Z:

Hi,
How are you launching the app using Java at command line. I am not much familiar with MAC env. I have it working in Linux. But on MAC I am not able to get the app to come up using "Java" at command line. The "JCEF_app" does work.

magreenblatt commented 10 years ago

Original comment by Anonymous.


Comment 5. originally posted by christophe.cornu on 2014-08-29T23:01:37.000Z:

Anth: I'm away from the mac I use for the next few days so i can't paste you the exact command line until then. It's pretty similar to Linux except the native libs and jars are in different folders. Yes the "JCEF_app" works, the pb is for those running without their own custom bundled app such as java/javaw/javaws. Maybe someone else will reply to you before I get back to you...

magreenblatt commented 10 years ago

Original comment by Anonymous.


Comment 6. originally posted by anthapu on 2014-08-31T18:33:03.000Z:

Hi Christopher,
That's not an issue. Please post it when you get a chance. I tried various options. Since the xcode also tries to hardcode the path to different libraries it becomes a bit contrived to get the command line working. I tried to change the PATH references of the built libraries to make it simpler also. I still couldn't get it to work.

magreenblatt commented 10 years ago

Original comment by Anonymous.


Comment 7. originally posted by anthapu on 2014-09-08T12:53:07.000Z:

Hi Christopher,
If you have access to your MAC, can you please post the command line?

magreenblatt commented 10 years ago

Original comment by Anonymous.


Comment 8. originally posted by christophe.cornu on 2014-09-09T13:11:00.000Z:

Hi Anth: here it is. It's very similar to the command line on Windows (run.bat).

Open console
Go to directory that contains jcef_app.app (e.g. <...>/jcef/src/xcodebuild/Release/
java -cp "./jcef_app.app/Contents/Java/*" -Djava.library.path=./jcef_app.app/Contents/Java tests.detailed.MainFrame

This works fine with revision92. With revision99, this fails with the following output:

java -cp "./jcef_app.app/Contents/Java/*" -Djava.library.path=./jcef_app.app/Contents/Java tests.detailed.MainFrame
Offscreen rendering disabled
Using:
JCEF Version = 3.1916.1749.99
CEF Version = 3.1916.1749
Chromium Version = 35.0.1916.138
initialize on Thread[AWT-EventQueue-0,6,main] with library path ./jcef_app.app/Contents/Java
Added scheme search://
Added scheme client://
[0909/090956:FATAL:content_main_runner.cc(751)] Check failed: base::i18n::InitializeICU().
Trace/BPT trap: 5

magreenblatt commented 10 years ago

Original comment by Anonymous.


Comment 9. originally posted by anthapu on 2014-09-09T14:58:18.000Z:

Thanks. That works.

magreenblatt commented 10 years ago

Original comment by Anonymous.


Comment 10. originally posted by christophe.cornu on 2014-09-23T15:20:40.000Z:

Thanks. That works.
Hi Anth... I'm suspended on your last words... Were you working on a Chromium patch to make the loading of icudtl.dat more flexible?

magreenblatt commented 10 years ago

Original comment by Anonymous.


Comment 11. originally posted by anthapu on 2014-09-23T16:17:55.000Z:

No. I was not able to get the MAC command line working. Your suggestion helped. I was trying to change the library paths using install_name_tool to change the directory structure to launch the app, as I wanted to customize the structure. But I couldn't get the Java command line working correctly.

I had the same problem in Linux and your issue report helped to work around that issue there.

Your suggestion helped getting it working on MAC.

Also, icudtl.dat may be part of the CEF issue. There were some people complaining about it had to be in the directory where the binary (CEFClient.exe) is located.

I have not found alternative yet.

magreenblatt commented 10 years ago

Original comment by Anonymous.


Comment 12. originally posted by christophe.cornu on 2014-09-23T16:45:40.000Z:

I'm afraid there's no alternative but to modify the code in https://chromium.googlesource.com/chromium/src/base/+/refs/heads/master/i18n/icu\_util.cc . Unfortunately it's not in JCEF or CEF, it's in Chromium.

magreenblatt commented 9 years ago

Original comment by Dmitry Azaraev (Bitbucket: Mystic Artifact).


It is not needed to fix icu_util.cc. Instead "fixing" of random files, better if CEF will provide own customizable PathService. icu_util already capable with path service and covers any platforms.

magreenblatt commented 9 years ago

Original comment by Trejkaz (pen name) (Bitbucket: Trejkaz).


If the issue is in Chromium, has it at least been filed with Chromium? I get a crash every time I run this thing.

Getting it working in a full application is one thing, but unless I can use the library while working in an IDE, who is going to build the application? Because I sure as hell can't...

magreenblatt commented 9 years ago

Original comment by Marcin (Bitbucket: Marcin, GitHub: Marcin).


any news on this issue ? This issue is also relevant for mac's CEF3 based dylib opened as a plugin by 3rd party application which forces a workaround to inject icudtl.dat into app boundle ....

magreenblatt commented 9 years ago

Original comment by Dominic E. (Bitbucket: Dominic E.).


The problem comes from chromium, not jcef... You have to set working directory to jcef_app.app or create an own bundle with right structure and set working directory to it.

You need mandatory an app-bundle with this structure: anyApp.app/Contents/Frameworks/Chromium Embedded Framework.framework/Resources and set resources_dir_path of browser settings

magreenblatt commented 9 years ago

Original comment by Marcin (Bitbucket: Marcin, GitHub: Marcin).


Thanks, I meant the issue in Chromium. Is is reported, what is the status ...

magreenblatt commented 9 years ago

Original comment by Mikael Gueck (Bitbucket: mikaelhg, GitHub: mikaelhg).


@fddima how big a task do you estimate creating a custom PathService would be?

magreenblatt commented 7 years ago

Original comment by Czarek Tomczak (Bitbucket: Czarek, GitHub: Czarek).


Discovery of icudtl.dat is fixable in upstream CEF on both Linux and Mac:

  1. Linux - if you can build from sources apply the CefOverridePath attached in CEF Issue #1936 or wait for CEF PR 66 to be reworked.

  2. Mac - branches 2924 and later have the CefSettings.framework_dir_path setting, see CEF Issue 1532 and this comment by Marshall

magreenblatt commented 7 years ago

Original comment by Andrew Thompson (Bitbucket: Andrew Thompson).


Naïve question, but is fixing this in CefSettings.java as simple as creating a public String with the name framework_dir_path and Magic Bridging Stuff™ happens, or is it more involved?

magreenblatt commented 7 years ago

You can make this work on macOS without changes to JCEF source code. Here's an example using a JCEF build at current master (CEF version 3.2987.1597.gffc5773) and extracting the contents from a Release build of jcef_app.app:

1. Create a directory structure like the following:

/path/to/jcef/
  run.sh
  bin/
    *.jar
    lib/macosx64/
      Chromium Embedded Framework.framework/
        Chromium Embedded Framework
        Resources/
          *.lproj, *.pak, etc.
      jcef Helper.app/
        Contents/
          Info.plist
          MacOS/jcef Helper
      libjcef.dylib

2. Fix name links for libjcef.dylib and jcef Helper:

$ cd /path/to/jcef/bin/lib/macosx64
$ install_name_tool -change "@rpath/Frameworks/Chromium Embedded Framework.framework/Chromium Embedded Framework" "@loader_path/Chromium Embedded Framework.framework/Chromium Embedded Framework" libjcef.dylib
$ install_name_tool -change "@executable_path/Chromium Embedded Framework.framework/Chromium Embedded Framework" "@executable_path/../../../Chromium Embedded Framework.framework/Chromium Embedded Framework" "jcef Helper.app/Contents/MacOS/jcef Helper"

3. Create run.sh with the following contents:

#!/bin/bash
# Absolute path to the library directory.
export LIB_PATH="/path/to/jcef/bin/lib/macosx64"

java -cp "./bin:./bin/*" -Djava.library.path=$LIB_PATH tests.detailed.MainFrame --framework-dir-path=$LIB_PATH/Chromium\ Embedded\ Framework.framework --browser-subprocess-path=$LIB_PATH/jcef\ Helper.app/Contents/MacOS/jcef\ Helper --disable-gpu

The --disable-gpu flag seems to be necessary at the moment to avoid silent failures when creating the child processes.

magreenblatt commented 7 years ago

Original comment by Wai Wang (Bitbucket: Wai Wang).


I created a simple hack for icudtl.dat discovery by copying over the java binary to a temporary folder and symlinking the libs directory so the general directory structure is like this:

tmpDirectory/fakeJvm/
    bin/
        java
        icudtl.dat
        natives_blob.bin
        snapshot_blob.bin
     lib/             <- Symlink to JRE lib directory

Then the program executes itself with the new java binary, code(in Kotlin): https://gist.github.com/waicool20/10619ab01f6cf26be4919a6670f17bdd

magreenblatt commented 7 years ago

Original comment by Jonathan Cremieux (Bitbucket: kremio, GitHub: kremio).


I can confirm that Marshall's setup from his post from the 29th of March 2017 works. It is very helpful, thanks!

However, with the JCEF build at current master (CEF version 3.3029.1604.g364cd86), I had to slightly modify the 2nd call to install_name_tool:

#!bash

install_name_tool -change "@rpath/Frameworks/Chromium Embedded Framework.framework/Chromium Embedded Framework" "@executable_path/../../../Chromium Embedded Framework.framework/Chromium Embedded Framework" "jcef Helper.app/Contents/MacOS/jcef Helper
magreenblatt commented 6 years ago

Original comment by Stefan Arisona (Bitbucket: arisona, GitHub: arisona).


Are there any insights / known reasons why "--disable-gpu" is needed? I need to add it when using CEF from Java, otherwise the window remains white. If I run the same code directly from the command line, disabling the GPU is not necessary.

magreenblatt commented 6 years ago

Original comment by Mark van de Korput (Bitbucket: markkorput, GitHub: markkorput).


@magreenblatt's solution finally shed some light in the dark of these breaking dependency references when trying to embed cef in another java host application. For reference, here is my slight modification of his patch and run commands (using also the same modification that @kremio applied). My scripts work with the unmodified jcef_app.app, no need to build the custom structure that @magreenblatt suggested;

patch.sh

#!sh
install_name_tool -change "@rpath/Frameworks/Chromium Embedded Framework.framework/Chromium Embedded Framework" "@loader_path/../Frameworks/Chromium Embedded Framework.framework/Chromium Embedded Framework" ./jcef_app.app/Contents/Java/libjcef.dylib
install_name_tool -change "@rpath/Frameworks/Chromium Embedded Framework.framework/Chromium Embedded Framework" "@executable_path/../../../Chromium Embedded Framework.framework/Chromium Embedded Framework" "./jcef_app.app/Contents/Frameworks/jcef Helper.app/Contents/MacOS/jcef Helper"

run.sh

#!sh
#!/bin/bash
JAVA_PATH="./jcef_app.app/Contents/Java"
FRAMEWORKS_PATH="./jcef_app.app/Contents/Frameworks"
RESOURCES_DIR_PATH="$(pwd)/jcef_app.app/Contents/Frameworks/Chromium Embedded Framework.framework/Resources"
java -cp "$JAVA_PATH:$JAVA_PATH/*" -Djava.library.path=$JAVA_PATH tests.detailed.MainFrame --framework-dir-path=$FRAMEWORKS_PATH/Chromium\ Embedded\ Framework.framework --browser-subprocess-path=$FRAMEWORKS_PATH/jcef\ Helper.app/Contents/MacOS/jcef\ Helper --resources-dir-path="$RESOURCES_DIR_PATH" --disable-gpu

Put these patch.sh and run.sh files in the same folder as your jcef_app.app (path/to/jcef/src/jcef_build/native/Release/ if you followed the build wiki using the cmake method) and run the patch.sh ONCE to patch the internal executable references. Then run the run.sh to run the app java test application.

NOTE; this issue has been around for 4 years and has 14 votes, should the "minor" status be revisited? Seeing also that it basically renders jcef unusable to embedded in java host applications on the mac.

magreenblatt commented 5 years ago

For Linux this has been fixed upstream in https://bitbucket.org/chromiumembedded/cef/issues/1936

magreenblatt commented 5 years ago

Original comment by Bart Adriaanse (Bitbucket: adriaanse, GitHub: adriaanse).


Do we need to wait for an update of JCEF for this fix ?

Triggered by the security alerts last week I am building a JCEF update (with JDK 11.01) according to the instructions in the Wiki but the native dll's (win64) I get are 3.3626.* versions and on linux I still need to put these files in the jre/bin folder or the application fails hard...

magreenblatt commented 5 years ago

@adriaanse JCEF needs to be built against the correct CEF branch/version. The version is controlled in CMakeLists.txt. The Linux fix mentioned above will soon be available in 3683 branch builds.

magreenblatt commented 5 years ago

Original comment by Bart Adriaanse (Bitbucket: adriaanse, GitHub: adriaanse).


OK, good to know, thank you !

magreenblatt commented 5 years ago

Original comment by Bart Adriaanse (Bitbucket: adriaanse, GitHub: adriaanse).


Given the recent 99ee032 (bb) commit, I just rebuilt and tested this issue on both CentOS 7 and Ubuntu 14 so i can confirm that it works !

magreenblatt commented 5 years ago

Original comment by Rene Schneider (Bitbucket: S1artie, GitHub: S1artie).


I can confirm this to be working as well. I've had a preliminary fix for this problem in my JCEF branch and dropped it for the build against CEF 3683. Application still working just fine (on CentOS 7 in my case).

magreenblatt commented 5 years ago

Original comment by Frantisek Kolar (Bitbucket: Frantisek Kolar).


@Mark van de Korput, I just found your comment and I wonder if its possible to share something working. When i try to follow all the instruction for simple app, I just get allot of exception type of: UnsatisfiedLinkError.

So not sure if these steps might not be working for current version or used to work for something that was valid a year ago - or I do something completly wrong.

Thanks for any hints.

magreenblatt commented 4 years ago

macOS: Support command-line configuration of framework-dir-path (see issue #109)

If specified via the command-line the framework-dir-path value will be used locate the "Chromium Embedded Framework" library for dynamic loading by JCEF.

For example, create the following directory structure:

/path/to/jcef/
  run.sh
  bin/
    *.jar
    lib/macos64/
      Chromium Embedded Framework.framework/
        Chromium Embedded Framework
        Resources/
          *.lproj, *.pak, etc.
      jcef Helper[ (GPU)| (Plugin)| (Renderer)].app/
        Contents/
          Info.plist
          MacOS/jcef Helper
      libjcef.dylib

And create run.sh with the following contents:

export LIB_PATH="/path/to/jcef/bin/lib/macos64"

java -cp "./bin:./bin/*" -Djava.library.path=$LIB_PATH tests.detailed.MainFrame
  --framework-dir-path=$LIB_PATH/Chromium\ Embedded\ Framework.framework
  --main-bundle-path=$LIB_PATH/jcef\ Helper.app
  --browser-subprocess-path=$LIB_PATH/jcef\ Helper.app/Contents/MacOS/jcef\ Helper
  --disable-gpu

The app bundle path passed to --main-bundle-path is used for determining an app bundle ID and locating the optional Contents/Resources/crash_reporter.cfg file. It can point to any valid app bundle.

→ <<cset cbde7f9d45d3 (bb)>>

magreenblatt commented 4 years ago

Original comment by Rene Schneider (Bitbucket: S1artie, GitHub: S1artie).


@{557058:2f2a2aee-b500-4023-9734-037e9897c3ab} Huge thanks to you for adding that latest commit! This is super practical! I was using some similar, but more intrusive and hacky version of that on my branches in order to allow for dynamic extraction of CEF from JARs. Was able to drop that now and adopted your solution (I also didn’t know about the --main-bundle-path parameter, which is nicer than patching around in Chromium code to fix the bundle ID problem).

magreenblatt commented 4 years ago

Original comment by Steve Hannah (Bitbucket: shannahcn1).


Can someone explain why this problem is difficult to solve? If I want to include JCEF in a Java project, without wrapping it inside an .app bundle, it seems the only solution is to add symlinks into my JDK. Otherwise we get

[0623/092048.019986:ERROR:icu_util.cc(168)] icudtl.dat not found in bundle

[0623/092048.020215:ERROR:icu_util.cc(241)] Invalid file descriptor to ICU data received.

Is there a way to use JCEF in a Java project without wrapping it in an .app bundle, and without modifying the JDK?

I’m poking around the sources to see if I can find an easy way to tell it where to find icudtl.dat, but I’d appreciate any pointers to help me understand why this problem is hard to solve or where I need to look to solve it.

magreenblatt commented 4 years ago

@{557058:b8c4fa7e-a54b-43e4-bd90-fed75b3e5e0f} Did you see the “official response” pinned at the top of this issue?

magreenblatt commented 4 years ago

Original comment by Steve Hannah (Bitbucket: shannahcn1).


@{557058:2f2a2aee-b500-4023-9734-037e9897c3ab} Sorry. Didn’t notice that that was pinned and official. I had tried that first and it wasn’t working for me. Now that I know that that is the official solution, I’ll spend more time trying variations on that.

magreenblatt commented 3 years ago

Original comment by Gulshan Bhatia (Bitbucket: Gulshan Bhatia).


HI,

@{5cdc7c96344d8f0e3fba6706}

I tried whatever steps are mentioned and now I am able to run the sample examples by JCEF which is mentioned in the run.sh but when I tried to put my class files in the same folder and added that class name in run.sh the. it give me a class not found error.

magreenblatt commented 3 years ago

Original comment by Gulshan Bhatia (Bitbucket: Gulshan Bhatia).


Hi Guys,

With the above hack, provided by the @{557058:80acce41-5a84-43d8-b61c-93ea3bcea2a8} by creating patch.sh and run.sh sample application is tests.detailed.MainFrame working completely fine.

But can someone tell me how can I run my java jcef app? where can I put my java file to compile .class file and where can I put my class file to run from run.sh?

Also @{557058:80acce41-5a84-43d8-b61c-93ea3bcea2a8} can you please let me know from where sample app ests.detailed.MainFrame is executed?