“unknown protocol: data” when using data URIs in IMG tags displayed by JavaFX WebView

。_饼干妹妹 提交于 2020-01-23 02:58:04

问题


Apologies for the title, I tried to be concise, but it's hard to be in this case.

I'm building an application that uses JavaFX's WebView class to display a list of SVG images.

Because they need to fit into their parents' width (which can change), I was forced to use <img> tags with data URIs rather than inline <svg> (I won't go into detail on this problem here, but it's a flaw of the WebKit engine used by WebView which prevents <svg> elements from adjusting their height according to their width which works fine in current Firefox versions).

Therefore, the innerHTML of the containing element may look like this (most Base64 data omitted):

<img src="data:image/svg+xml;base64,PHN2Zy[...]" style="width: 100%;">
<img src="data:image/svg+xml;base64,PD94bW[...]" style="width: 100%;">

This displays the images just fine. However, I came across some curious behaviour: as soon as I did some dragging and dropping of the images (just some idle motion while thinking, no expected behaviour to go along with that), this exception showed up:

Exception in thread "JavaFX Application Thread" java.lang.IllegalArgumentException: Invalid URL: unknown protocol: data
    at javafx.scene.image.Image.validateUrl(Image.java:1121)
    at javafx.scene.image.Image.<init>(Image.java:620)
    at com.sun.javafx.tk.quantum.QuantumClipboard.readImage(QuantumClipboard.java:400)
    at com.sun.javafx.tk.quantum.QuantumClipboard.getContent(QuantumClipboard.java:291)
    at javafx.scene.input.Clipboard.getContentImpl(Clipboard.java:261)
    at javafx.scene.input.Dragboard.getContentImpl(Dragboard.java:62)
    at javafx.scene.input.Clipboard.getContent(Clipboard.java:254)
    at javafx.scene.web.WebView.lambda$registerEventHandlers$35(WebView.java:1170)
    at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:86)
    at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238)
    at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
    at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
    at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:54)
    at javafx.event.Event.fireEvent(Event.java:198)
    at javafx.scene.Scene$DnDGesture.handleExitEnter(Scene.java:3210)
    at javafx.scene.Scene$DnDGesture.processTargetEnterOver(Scene.java:3098)
    at javafx.scene.Scene$DnDGesture.access$6100(Scene.java:2909)
    at javafx.scene.Scene$DropTargetListener.dragEnter(Scene.java:2813)
    at com.sun.javafx.tk.quantum.GlassSceneDnDEventHandler.lambda$handleDragEnter$307(GlassSceneDnDEventHandler.java:70)
    at java.security.AccessController.doPrivileged(Native Method)
    at com.sun.javafx.tk.quantum.GlassSceneDnDEventHandler.handleDragEnter(GlassSceneDnDEventHandler.java:65)
    at com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleDragEnter$361(GlassViewEventHandler.java:661)
    at com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:389)
    at com.sun.javafx.tk.quantum.GlassViewEventHandler.handleDragEnter(GlassViewEventHandler.java:660)
    at com.sun.glass.ui.View.handleDragEnter(View.java:688)
    at com.sun.glass.ui.View.notifyDragEnter(View.java:1020)
    at com.sun.glass.ui.gtk.GtkDnDClipboard.pushToSystemImpl(Native Method)
    at com.sun.glass.ui.gtk.GtkDnDClipboard.pushToSystem(GtkDnDClipboard.java:39)
    at com.sun.glass.ui.SystemClipboard.flush(SystemClipboard.java:51)
    at com.sun.glass.ui.ClipboardAssistance.flush(ClipboardAssistance.java:59)
    at com.sun.javafx.tk.quantum.QuantumClipboard.flush(QuantumClipboard.java:274)
    at com.sun.javafx.tk.quantum.QuantumToolkit.startDrag(QuantumToolkit.java:1224)
    at javafx.scene.Scene$DnDGesture.dragDetectedProcessed(Scene.java:2953)
    at javafx.scene.Scene$DnDGesture.process(Scene.java:3022)
    at javafx.scene.Scene$DnDGesture.access$8200(Scene.java:2909)
    at javafx.scene.Scene$MouseHandler.process(Scene.java:3773)
    at javafx.scene.Scene$MouseHandler.access$1500(Scene.java:3485)
    at javafx.scene.Scene.impl_processMouseEvent(Scene.java:1762)
    at javafx.scene.Scene$ScenePeerListener.mouseEvent(Scene.java:2494)
    at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:380)
    at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:294)
    at java.security.AccessController.doPrivileged(Native Method)
    at com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleMouseEvent$354(GlassViewEventHandler.java:416)
    at com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:389)
    at com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(GlassViewEventHandler.java:415)
    at com.sun.glass.ui.View.handleMouseEvent(View.java:555)
    at com.sun.glass.ui.View.notifyMouse(View.java:937)
    at com.sun.glass.ui.gtk.GtkApplication._runLoop(Native Method)
    at com.sun.glass.ui.gtk.GtkApplication.lambda$null$49(GtkApplication.java:139)
    at java.lang.Thread.run(Thread.java:745)
Caused by: java.net.MalformedURLException: unknown protocol: data
    at java.net.URL.<init>(URL.java:600)
    at java.net.URL.<init>(URL.java:490)
    at java.net.URL.<init>(URL.java:439)
    at javafx.scene.image.Image.validateUrl(Image.java:1115)
    ... 58 more

On closer inspection I learned that it does this every time I try to drag an image; everything else is fine.

So I have to wonder: what did that dragging and dropping do to cause those errors? And how do I stop it?

Some notes:

  • The SVG data is created "on the fly" and at no point does it exist on the disk.
  • Writing the data to disk is not an option.
  • They need to be SVG images.

[edit: updated the question according to new observation that the effect only occurs by dragging images and only once per attempt.]


回答1:


As already mentioned in my comment, it's an open bug in JavaFX: https://bugs.openjdk.java.net/browse/JDK-8160597

But it seems I have found a workaround. I just had to add three listeners to the web view for the drag events which do nothing at all, not even consume the event. After that text selection in the web view still worked and the exception while dragging the images vanished:

webview {
  setOnDragEntered {
  }

  setOnDragOver {
  }

  setOnDragExited {
  }
}

This is Kotlin code, as I'm developing in Kotlin with TornadoFX (a JavaFX wrapper). I'm guessing in Java the code would look pretty similar. Just call the three set methods directly on the web view object and add an anonymous class with an empty handle method. Or use an empty lambda expression, if you are using newer Java versions.



来源:https://stackoverflow.com/questions/45398912/unknown-protocol-data-when-using-data-uris-in-img-tags-displayed-by-javafx-we

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!