From 7.16 to 7.17

In this migration guide we describe what API has been removed in 7.17 and what alternatives you should use instead.

Loading HTML

v7.16

To load HTML from string into a frame on a web page the following Frame methods are used:

  • loadHtml(String html)
  • loadHtml(LoadHtmlParams params)
  • loadData(LoadDataParams params)

v7.17

In the recent Chromium builds the functionality that allows loading HTML into a frame on a web page has been changed for security reasons and doesn’t work properly anymore. For example, if the loaded HTML has external images located on a web server, they will not be loaded and displayed.

To get rid of unexpected behavior and potential bugs, we decided to remove these methods and suggest the following alternative approaches to load HTML from string.

By loading Data URL:

String html = "<html><body>Hello</body></html>";
String base64Html = Base64.getEncoder().encodeToString(html.getBytes(UTF_8));
String dataUrl = "data:text/html;charset=utf-8;base64," + base64Html;
browser.navigation().loadUrl(dataUrl);
val html = "<html><body>Hello</body></html>"
val base64Html = Base64.getEncoder().encodeToString(html.toByteArray(UTF_8))
val dataUrl = "data:text/html;charset=utf-8;base64,$base64Html"
browser.navigation().loadUrl(dataUrl)

By registering a custom scheme and intercepting the required URL requests:

InterceptUrlRequestCallback interceptCallback = params -> {
    if (params.urlRequest().url().endsWith("?hello")) {
        byte[] bytes = "<html><body>Hello</body></html>".getBytes();
        UrlRequestJob job = params.newUrlRequestJob(
                UrlRequestJob.Options
                .newBuilder(HttpStatus.OK)
                .addHttpHeader(HttpHeader.of("Content-Type", "text/html"))
                .build());
        job.write(bytes);
        job.complete();
        return Response.intercept(job);
    }
    return Response.proceed();
};

EngineOptions options = EngineOptions.newBuilder(renderingMode)
        .addScheme(HTTP, interceptCallback)
        .build();
Engine engine = Engine.newInstance(options);
Browser browser = engine.newBrowser();
browser.navigation().loadUrl("http://load.html/?hello");
val interceptCallback = InterceptUrlRequestCallback { params ->
    if (params.urlRequest().url().endsWith("?hello")) {
        val bytes = "<html><body>Hello</body></html>".toByteArray()
        val job = params.newUrlRequestJob(
            UrlRequestJob.Options
                .newBuilder(HttpStatus.OK)
                .addHttpHeader(HttpHeader.of("Content-Type", "text/html"))
                .build()
        )
        job.write(bytes)
        job.complete()
        Response.intercept(job)
    } else {
        Response.proceed()
    }
}

val options = EngineOptions.newBuilder(renderingMode)
        .addScheme(HTTP, interceptCallback)
        .build()
val engine = Engine.newInstance(options)
val browser = engine.newBrowser()
browser.navigation().loadUrl("http://load.html/?hello"))

Read more about these approaches in Navigation.

System properties

The following internal system properties have been removed:

  • jxbrowser.display.watcher.off
  • jxbrowser.enable.custom.dropdowns

Use the jxbrowser.desktop.headless.on system property instead to disable display watcher and enable custom drop downs in the off-screen rendering mode.

Go top