JDK-8152420 : [WebView] Icon font doesn't work if single page application will be loaded from jar
  • Type: Bug
  • Component: javafx
  • Sub-Component: web
  • Affected Version: 8u74,9
  • Priority: P3
  • Status: Resolved
  • Resolution: Fixed
  • OS: windows_8
  • CPU: x86
  • Submitted: 2016-03-09
  • Updated: 2016-08-04
  • Resolved: 2016-04-28
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
8u112Fixed 9Fixed
Related Reports
Cloners :  
Duplicate :  
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
java version "1.8.0_74"
Java(TM) SE Runtime Environment (build 1.8.0_74-b02)
Java HotSpot(TM) 64-Bit Server VM (build 25.74-b02, mixed mode)

Microsoft Windows [Version 6.3.9600]

I sumbitted the following bug which was fixed with 8u72. 

No I tried to use an icon font in my application and now I've found the next issue:
-> icon fonts doesn't work if a single page application will be loaded from a resource.

I extended my example:

Please verify if another resource loader is affected. 

Thanks in advance,

REGRESSION.  Last worked in version 8u74

This bug can be reproduced always.

Changeset: 1ec63f261e9f Author: ghb Date: 2016-04-28 15:07 +0530 URL: http://hg.openjdk.java.net/openjfx/9-dev/rt/rev/1ec63f261e9f 8152420: [WebView] Icon font doesn't work if single page application will be loaded from jar Reviewed-by: ddhill, kcr

Looks fine. +1

Code changes look fine. (one suggestion: you might want to do the 'new File(System.getProperties().get("WEB_ARCHIVE_JAR_TEST_DIR").toString()' once and store it into a local variable). I'd like to run a test in jigsaw mode to make sure there are no issues there (I suspect it will run fine). I'll do that in the next hour.


Updated webrev http://cr.openjdk.java.net/~ghb/8152420/webrev.02/ Incorporated review comments Dave's review comments and removed white space.

There is a whitespace problem in your patch: ------------------------------------------------------------------------------------- $ gradle checkrepo ... :checkrepo build.gradle :trailingWhitespace: modules/web/src/test/java/test/javafx/scene/web/LoadTest.java :trailingWhitespace: Found 2 whitespace or executable issues To correct, use bash tools/scripts/checkWhiteSpace -F -x ------------------------------------------------------------------------------------- Please fix this and provide a webrev.02 (and you can address Dave's comments at the same time). I am reviewing the rest of it now.

Updated Webview http://cr.openjdk.java.net/~ghb/8152420/webrev.01/ (Unit test included) 1 : Create "webArchiveJar.jar" (Destination : "rt/modules/web/build/resources) from below listed html/js and add to classpath archive-root0.html -- src='archive-r0.js' src='c/archive-c0.js' archive-root1.html -- src='./archive-r0.js' src='./c/archive-c0.js' archive-root2.html -- src='./c/../archive-r0.js' src='./c/./././archive-c0.js' archive-r0.js -- function jsr0() { return 'loaded'} archive-c0.js -- function jsc0() { return 'loaded'} 2.Loads javascript "archive-r0.js" (root folder) and archive-c0.js (child folder) from three different html files. Assert return value of jsr0() and jsc0() function implemented in root js file and sub (child) folder c0.js. 3.failing to load js files will result in exception "netscape.javascript.JSException: ReferenceError: Can't find variable: jsr0() or jsc0() Tested on windows and Linux.

Test application 1. java -jar WebResourceFromJar.jar 2. java -jar WebResourceFromJar.jar jar:http://cr.openjdk.java.net/~ghb/8152420/tc/8152420.jar!/net/openjdk/JDK8152420/html/root.html Test content loads multiple javascript and images present in nested (update 3 level) directory as mentioned below. root.html loads source with different pattern as mentioned below and has corresponding 'h1' elements with initial text 'default'. every javascript onload will update the text value from 'default' to the pattern name. failing to load any resource will show its respective 'h1' elements text as 'default' Test result : Two images and their should be no 'default' text on the webview display src pattern : c/c0.js c/gc/gc0.js c/gc/ggc/ggc0.js c/../r1.js c/gc/../../r2.js c/gc/ggc/../../../r3.js c/.././r4.js c/gc/../../././././././r5.js c/././././gc/../../././././././r6.js'> </script c/././gc/././ggc/../../../r7.js ./c/../r8.js ./c/gc/../../r9.js ./c/gc/ggc/../../../r10.js ./c/.././r11.js ./c/gc/../../././././././r12.js ./c/././././gc/../../././././././r13.js'> </scr ./c/././gc/././ggc/../../../r14.js ./c/./c1.js ./././././c/./c2.js ./c/gc/../././././././c3.js ./c/gc/gc1.js ./c/gc/ggc/ggc1.js ./c./gc./ggc./ggc2.js folder structure |____html | |____c | | |____c0.js | | |____c1.js | | |____c2.js | | |____c3.js | | |____gc | | | |____gc0.js | | | |____gc1.js | | | |____ggc | | | | |____ggc0.js | | | | |____ggc1.js | | | | |____ggc2.js | | | | |____openjdk.png | | |____openjdk.png | |____META-INF | | |____MANIFEST.MF | |____r0.js | |____r1.js | |____r10.js | |____r11.js | |____r12.js | |____r13.js | |____r14.js | |____r2.js | |____r3.js | |____r4.js | |____r5.js | |____r6.js | |____r7.js | |____r8.js | |____r9.js | |____root.html

OK, thanks for confirming. If you can test the Windows file form of the URL that would cover it I think.

except "jar:file:/C:/dir/dir/file.jar!/pkg/file.html", rest of the forms i have tested for both absolute and relative urls. Currently i am writing Unit test case which will test http, https, file (absolute, and relative).

I filed JDK-8153681to track the "jrt:" protocol.

Note that resources in a jar will be of one of the following forms: jar:http://host.domain.name/dir/dir/file.jar!/pkg/file.html jar:https://host.domain.name/dir/dir/file.jar!/pkg/file.html jar:file:/dir/dir/file.jar!/pkg/file.html jar:file:/C:/dir/dir/file.jar!/pkg/file.html You should test all of these cases. This reminds me that I need to file the issue to handle resources contained within the java runtime modular image: jrt:/module.name/pkg/file.html

For both case , the request scheme in URL class remains same i.e 'jar' load(MainClass.class.getResource("html/index.html").toExternalForm()) load("jar:http://localhost:8080/lc/html.jar!/html/index.html") keeping isJarFile in URL::isHierarchical(..) will also works if we check for !isJarFile(), This i had tested earlier and then later removed. As mentioned earlier this could lead to another bug where we wont set path, host and port.

Thanks @Guru. I'm not aware of this. BTW, what will be the url scheme for "jar:http://.."? jar ? / http ?/ jar:http? Will it work if we change URL::isHierarchical(..) as I suggested? I'm not sure.

"loaded from jar(java -jar app.jar" app.jar has html.jar + class files. Application is loaded with java -jar app.jar app.jar's Main class loads an url with MainClass { ... WebViewObj.getEngine.load(MainClass.class.getResource("html/index.html").toExternalForm()) } we can load the same jar from a http using "jar:" URL schema as WebViewObj.getEngine.load("jar:http://localhost:8080/lc/html.jar!/html/index.html") policy download or ignored will be treated if we try to load WebViewObj.getEngine.load("jar:http://localhost:8080/lc/html.jar").

1: Agree with "jar:" URL scheme. Now the path followed by scheme could be file or http:// , Tested by keeping a jar in local server and it worked for me. you can try keeping a jar file in server and provide the url a. ClassName.class.getResource("html/index.html").toExternalForm() --> jar:file:/C:/ws/jira/jdk-8152420_jar/jdk-master/webview/singlepage/dependency/html.jar!/webview/html/index.html b. You can load a jar kept on remote server as webengine.load(jar:http://localhost:8080/lc/jartest.jar!/rootiframe.html) 2 : obviously file:// will be a empty referer. Do you expect an empty Referer for an url mentioned in 1.b ? if yes, Then i will go with your solution.

>> 1. Assume that jar file is loaded from an remote resource which has a port & path name in the base url. In these case we wont set host and path name. I don't think we need to support this. As of now we support only "jar:" URL scheme, that means entire jfx app is loaded from jar(java -jar app.jar) and all other resource can be referred from the jar, e.g. webview.load("jar:html/index.html"). In case WebView is asked to load a jar file from remote server, it should be treated as policy download or ignored. >> 2. root.html (present in jar file) has an iframe. For Iframe first request, referrers (HTTP) path and host will not be added. Depends on how server will rely on referrers name. What will be the behavior if we load a main resource from file:// which has iframe. I guess it will be loaded with empty referrer.

isHierarchical used in canSetPathName() & canSetHostOrPort(). There is no harm is keeping isJarFile() as you mentioned, Since Jar files will neither have path or host or port. I feel redundant check will be done for other case (as mentioned above 2 api). It might regress for below scenario 1. Assume that jar file is loaded from an remote resource which has a port & path name in the base url. In these case we wont set host and path name. 2. root.html (present in jar file) has an iframe. For Iframe first request, referrers (HTTP) path and host will not be added. Depends on how server will rely on referrers name. I can go with your proposed solution with compromising redundant check and keep an eye on above 2 regression

Why can't we consider "jar:" as hierarchical in all the places? I mean change the definition of URL::isHierarchical() to consider "jar:" also. bool URL::isHierarchical() const { if (!m_isValid) return false; ASSERT(m_string[m_schemeEnd] == ':'); return m_string[m_schemeEnd + 1] == '/' || isJarFile(); }

webrev : http://cr.openjdk.java.net/~ghb/8152420/webrev.00/ Root Cause : for all non isHierarchical relative path (jar is also considered non hierarchical) resource were not resolved for relative path What is Hierarchical : Slash followed by colon '://' is considered as Hierarchical. All other (usually) data: and javascript: which has data in the URL are non hierarchical. For jar the root html url will be having 1. base : 'jar:html/root.html' // for root page 2. base : 'jar:html/root.html' , relative 'js/jsfile.js' 3. base : 'jar:html/root.html' , relative './js/jsfile.js' pre "JDK-8136466" fix none of the sub resource were loaded (image and JavaScript) from a jar file. 8136466 resolves only for case 2 (mentioned above) . For Case 3 the relative url needs to be parsed './' and '../' and provide the reachable relative path for the file reader as expected below. 2nd output : 'jar:html/js/jsfile.js' 3rd output : 'jar:html/js/jsfile.js' Solution : Instead of copying the relative url, parse the relative url as its already being done for http (hierarchical) in the 'default' case of URL::init(...) Test : Created a html.jar file which has root.html and it has 8 h1 elements ��������� dotslashjs.js ��������� js ������� ��������� js ������� ������� ��������� jsslashslashjs.js ������� ��������� jsslashjs.js ������� ��������� nodotjsslash.js ��������� jsnavback.js ��������� multiplecurrent.js ��������� multiplecurrentroot.js ��������� relativejs.js ��������� root.html // 8 h1 elements which updates the text from respective js files listed in the tree e.g : relativejs.js will update h1id0 with 'relativejs.js' -- document.getElementById('h1id0').textContent = 'relativejs.js'; Similarly all the 8 elements will is tested with various navigation using below path will updates its file name in the h1's text. relativejs.js ./dotslashjs.js js/nodotjsslash.js ./js/jsslashjs.js ./js/js/jsslashslashjs.js ./js/../jsnavback.js ././././././././multiplecurrent.js ./js/js/../../multiplecurrentroot.js Will update the "JDK-8153411" for Functional test.