How to debug a JavaFX webview? I find two ways,
- one is to attach external chrome debugger to JavaFX webview.
- Another is to inject firebug javascript.
Method#1 seems to use a bit of hacks like set access to private fields etc. Method#2 depends on firebuglite which seems to be obsolete now.
How should this be done in 2022. Are there any other methods, or better methods?
I am trying firebug lite approach as of now, and have made the javascript part of the maven project and trying to inject it as a string versus an external URL, because firebug seems to be properly public hosted nowhere now.
Refering to https://mcmap.net/q/501885/-javafx-webview-webengine-firebuglite-or-some-other-debugger
This is where I am right now :
package xyz.jphil.internal_browser;
import com.sun.net.httpserver.HttpContext;
import com.sun.net.httpserver.HttpServer;
import java.net.InetSocketAddress;
import javafx.scene.web.WebEngine;
import netscape.javascript.JSObject;
/**
*
* @author Ivan
*/
public class WebkitDebugUtils {
private static int resourcesPort = 0;
public static void createHttpServerForLocalFiles() {
int portStart = 64321, endPort = 65534;
resourcesPort = portStart + (int) ((endPort * 1d - portStart * 1d) * Math.random());
System.out.println("Starting internal server on " + resourcesPort);
try {
HttpServer server = HttpServer.create(new InetSocketAddress(resourcesPort), 0);
HttpContext context = server.createContext("/");
context.setHandler((req) -> {
try (req) {
var p = req.getRequestURI();
System.out.println("Serving @ localhost:"+resourcesPort+" "+p);
var s = WebkitDebugUtils.class.getResourceAsStream(p.toString()).readAllBytes();
req.sendResponseHeaders(200, s.length);
req.getResponseBody().write(s);
}catch(Exception a){
a.printStackTrace();
}
});
server.start();
} catch (Exception e) {
e.printStackTrace();
}
}
public static class JavaBridge {
public void log(String text) {
System.out.println(text);
}
}
// Maintain a strong reference to prevent garbage collection:
// https://bugs.openjdk.java.net/browse/JDK-8154127
private final static JavaBridge bridge = new JavaBridge();
public static void enableDebug(final WebEngine e) {
JSObject window = (JSObject) e.executeScript("window");
window.setMember("java", bridge);
e.executeScript("""
console.log = function(message)
{
java.log(message);
};""");
e.executeScript("console.log('console.log enabled');");
}
public static void enableFirebug(final WebEngine e) {
var firebugurl = "http://localhost:"+resourcesPort+"/firebug-lite/firebug-lite.js";
//https://raw.githubusercontent.com/stefanXO/firebug-lite/master/firebug-lite.js
//https://lupatec.eu/getfirebug/firebug-lite-compressed.js
var script= """
console.log("Inside script block");
if (!document.getElementById("FirebugLite")) {
E = document["createElement" + "NS"] && document.documentElement.namespaceURI;
E = E ?
document["createElement" + "NS"](E, "script") :
document["createElement"]("script");
E["setAttribute"]("id", "FirebugLite");
E["setAttribute"]("src", "{$firebugurl}#startOpened");
E["setAttribute"]("FirebugLite", "4");
(
document["getElementsByTagName"]("head")[0]
||
document["getElementsByTagName"]("body")[0]
).appendChild(E);
E = new Image();
E["setAttribute"]("src", "{$firebugurl}#startOpened");
}
console.log("executed script block");
""".replace("{$firebugurl}", firebugurl);
System.out.println("+++firebug thing+++");
System.out.println(script);
System.out.println("---firebug thing---");
e.executeScript(script);
}
}
Main method of the application
//...
public static void main(String[]args){
WebkitDebugUtils.createHttpServerForLocalFiles();
launch(args);
}
//...
In the JavaFx Stage initializing code section
@Override
public void start(final Stage primaryStage) throws Exception {
// ....
wv = new WebView();
// ....
javafx.scene.web.WebEngine e = wv.getEngine();
// ....
e.getLoadWorker().stateProperty().addListener((ov, t, t1) -> WebkitDebugUtils.enableDebug(e));
e.documentProperty().addListener((ov, t, t1) -> WebkitDebugUtils.enableFirebug(e));
// ....
}
I am serving the files for firebug from the resources folder of the jar
Snippter of the custom firebug.js file
console.log("inside firebug-lite");
(function(){
//...
//firebug lite 1.4.0 code
//..
})();
console.log("outside firebug-lite");
Output
Starting internal server on 65148
console.log enabled
console.log enabled
// some application specific output
+++firebug thing+++
if (!document.getElementById("FirebugLite")) {
E = document["createElement" + "NS"] && document.documentElement.namespaceURI;
E = E ?
document["createElement" + "NS"](E, "script") :
document["createElement"]("script");
E["setAttribute"]("id", "FirebugLite");
E["setAttribute"]("src", "http://localhost:65148/firebug-lite/firebug-lite.js#startOpened");
E["setAttribute"]("FirebugLite", "4");
(
document["getElementsByTagName"]("head")[0]
||
document["getElementsByTagName"]("body")[0]
).appendChild(E);
E = new Image();
E["setAttribute"]("src", "http://localhost:65148/firebug-lite/firebug-lite.js#startOpened");
}
---firebug thing---
Inside script block
executed script block
Serving @ localhost:65148 /firebug-lite/firebug-lite.js
// some application specific output
console.log enabled
Summary: nothing is happening, nothing is showing up in the console, I don't know the error, firebug is not even opening.
Update2: I think I am using the wrong version of firebug 1.5 or something and the old version I don't see any HTML file and thus it is dependent on the default website which is down at the moment.
} catch (Exception a) { }
. If it can't find the resource, you silently ignore it and return an empty string. Squashing exceptions is a bad idea. – Vinaigrette