Posted on July 30, 2019
JxBrowser 7.1
Please meet the new JxBrowser 7.1!
In this update we concentrated on restoring the temporary dropped features and extending the current functionality with new possibilities.
Intercept mouse and keyboard events
Now you can intercept mouse and keyboard events before they are sent to the web page using the following callbacks:
EnterMouseCallback
ExitMouseCallback
MoveMouseCallback
MoveMouseWheelCallback
PressKeyCallback
PressMouseCallback
ReleaseKeyCallback
ReleaseMouseCallback
TypeKeyCallback
The following example demonstrates how to suppress mouse wheel:
browser.set(MoveMouseWheelCallback.class, params -> Response.suppress());
You can use these callbacks to get notifications about the mouse and keyboard events in order to implement hotkeys in your application.
Access bitmap of a web page
Now you can take a bitmap that contains
the pixels of the currently loaded web page with the current Browser
size. The following example demonstrates how to
get a bitmap, convert it to a Java AWT and JavaFX images, and save it to a PNG file:
Swing
// Creating and running Chromium engine.
Engine engine = Engine.newInstance(
EngineOptions.newBuilder(HARDWARE_ACCELERATED).build());
Browser browser = engine.newBrowser();
// Resize browser to the required dimension.
browser.resize(500, 500);
// Load the required web page and wait until it is loaded completely.
browser.navigation().loadUrlAndWait("https://www.google.com");
// Take a bitmap of the currently loaded web page. Its size will be
// equal to the current browser's size.
Bitmap bitmap = browser.bitmap();
// Convert the bitmap to java.awt.image.BufferedImage.
BufferedImage bufferedImage = BitmapUtil.toBufferedImage(bitmap);
// Save the image to a PNG file.
ImageIO.write(bufferedImage, "PNG", new File("bitmap.png"));
JavaFX
// Creating and running Chromium engine.
Engine engine = Engine.newInstance(
EngineOptions.newBuilder(HARDWARE_ACCELERATED).build());
Browser browser = engine.newBrowser();
// Resize browser to the required dimension.
browser.resize(500, 500);
// Load the required web page and wait until it is loaded completely.
browser.navigation().loadUrlAndWait("https://www.google.com");
// Take a bitmap of the currently loaded web page. Its size will be
// equal to the current browser's size.
Bitmap bitmap = browser.bitmap();
// Convert the bitmap to javafx.scene.image.Image.
Image image = BitmapUtil.toImage(bitmap);
// Convert javafx.scene.image.Image to java.awt.image.BufferedImage.
BufferedImage bufferedImage = SwingFXUtils.fromFXImage(image, null);
// Save the image to a PNG file.
ImageIO.write(bufferedImage, "PNG", new File("bitmap.png"));
JavaScript-Java bridge
@JsAccessible
Now the @JsAccessible
annotation can be used on class. It will mean that all public methods of the injected Java
object annotated with @JsAccessible
are accessible from JavaScript.
Automatic types conversion
We improved the JavaScript-Java bridge functionality and introduced automatic types conversion when calling a public
method of the injected Java object from JavaScript. In V7.0 the JavaScript Number
could be converted only to
Java Double
.
Now the library automatically converts the given JavaScript Number
to the required Java type if it is possible. If
we detect that the given number cannot be converted to, for example, a Java byte
without data loss, then the library
throws an exception and notifies JavaScript that there is no appropriate Java method. If the given value can be
converted without data loss, then the library converts it and invokes the appropriate Java method.
For example, if you inject the following Java object into JavaScript:
@JsAccessible
public final class JavaObject {
public int method(int intValue) {
return intValue;
}
}
Then you can call it from JavaScript and pass the JavaScript Number
value that can be converted to an Integer
without data loss:
window.javaObject.method(123);
But, if you pass Double
value that cannot be converted to an Integer
without data loss, you will get an error:
window.javaObject.method(3.14); // <- error
JsFunctionCallback
JavaScript-Java bridge allows you to associate Java object or a primitive value with a JavaScript property. Now, you can
associate JsFunctionCallback
with a JavaScript property that will be treated as a function that can be invoked in
JavaScript code.
For example, you can register a JavaScript function associated with the JsFunctionCallback
instance using the
following code:
JsObject window = frame.executeJavaScript("window");
if (window != null) {
window.putProperty("sayHello", (JsFunctionCallback) args ->
"Hello, " + args[0]);
}
Now in JavaScript you can invoke this function in the following way:
window.sayHello('John');
WebStorage API
You can access the Local and Session storage and work with it from the Java code directly:
WebStorage localStorage = frame.localStorage();
localStorage.putItem("car", "BMW");
localStorage.clear();
Remote debugging URL
In 7.1 we restored functionality that allows
getting the remote debugging URL for a web page loaded in a particular Browser
instance. The following example
demonstrates how to do it:
browser.devTools().remoteDebuggingUrl().ifPresent(url -> {});
JFXPanel
JxBrowser provides two BrowserView
components for both Swing and JavaFX applications. We recommend you to use
Swing BrowserView
in Swing applications, and JavaFX BrowserView
in JavaFX applications.
Sometimes you might need to embed JavaFX BrowserView
into a Swing application. For example, if you develop a complex
web browser control using JavaFX UI Toolkit and you have to display this JavaFX control in a Swing/AWT application.
Now you can embed JavaFX BrowserView
into a Swing/AWT
window through JFXPanel
. It is supported on all supported platforms with all rendering modes.
Select media device
If you have multiple webcams and microphones in your environment, and a web page wants to use one of them, you can
use SelectMediaDeviceCallback
to tell the web page which device should be used.
The following example demonstrates how to select the first device in the list of available devices:
engine.mediaDevices().set(SelectMediaDeviceCallback.class, params ->
Response.select(params.mediaDevices().get(0)));
If you would like to forbid the web page to access your microphone or a webcam, you can use RequestPermissionCallback
as shown below:
engine.permissions().set(RequestPermissionCallback.class, (params, tell) -> {
PermissionType type = params.permissionType();
if (type == PermissionType.VIDEO_CAPTURE || type == PermissionType.AUDIO_CAPTURE) {
tell.deny();
} else {
tell.grant();
}
});
Access HTTP response body
In JxBrowser 7.0 we introduced the BytesReceived
event that allows getting the information about the amount of bytes
received from the network. In this version we added ResponseBytesReceived
that allows accessing the bytes of the HTTP
response body:
network.on(ResponseBytesReceived.class, event -> {
byte[] data = event.data();
});
Hiding scrollbars
Now you can hide scrollbars using the following approach:
browser.settings().hideScrollbars();
Once you called this method, the web pages loaded in the Browser
instance will not display scrollbars anymore. It is
useful for kiosk applications and when you are taking bitmap of a web page.
DOM API
Element
The Element
has been extended with the following methods:
focus()
andblur()
allow programmatically set the keyboard focus to a focusable HTML element and clear the focus.outerHtml()
allow getting a string that represents an HTML serialization of theElement
and its descendants.
Node.document()
Starting from V7.1 you can get the Document
instance of a Node
instance. For example:
Document document = node.document();
I18N internationalization
The library now supports internationalization (I18N) when browsing local file system:
Download API
We extended JxBrowser API with functionality that allows you to get the Browser
instance that has initiated download
using the following code:
downloads.set(StartDownloadCallback.class, (params, tell) -> {
params.browser().ifPresent(browser -> {
...
});
tell.cancel();
});
Please note that Browser
instance might be already closed or not available by the time when download starts. This is
why we use Optional<Browser>
in the API.
Disable touch menu
We extended the EngineOptions
with additional option that allows disabling touch menu on Windows 10 touch devices. The
following code snippet demonstrates how to disable touch menu:
Engine engine = Engine.newInstance(
EngineOptions.newBuilder(renderingMode)
.disableTouchMenu()
.build());
Request focus event
To get notifications when JavaScript requests focus via window.focus()
you can use the FocusRequested
event:
browser.on(FocusRequested.class, event -> {});
Language API
The Language
enum has been extended with the Language.of(String language, String country)
static method that obtains
the corresponding Language
enum item for the given language and country.
We recommend you to use this method instead of Language.of(Locale)
if there is a need to pass the new language codes
instead of the old ones, because Java Locale
internally converts the new language code passed to the constructor to
the old one. There is a chance not to find a language for an old code, so if you want to be sure that the passed locale
will not be converted, use this method with the required language and country codes.
Certificate.toX509Certificate()
The Certificate
class has been extended with the Optional<X509Certificate> toX509Certificate()
method that allows
getting an X.509 certificate initialized with the data stored in the certificate’s DER-encoded array of bytes.
Improvements
- Detect when Java process is unexpectedly terminated with the
kill -9
signal on macOS or Linux and terminate thebrowsercore
processes created by the killed Java process. - Update the details of the
browsercore.exe
process on Windows. XPathResult.asSingleNode()
returns an emptyOptional
instead of throwing exception when the node was not found.- Default implementations of the
StartDownloadCallback
for both Swing and JavaFXBrowserView
components. Now when you try to download a file, a default Save File dialog will be displayed where you can select where to download and save the file. Unless you register your own callback and override the default behavior. - Reduce black flickering on Windows when displaying Swing
BrowserView
for the first time.
Fixed Issues
- Restore macOS 10.10 support.
- The
Engine
language option ignored and alwaysENGLISH_US
on Linux when working on macOS and Windows. - The main frame of the popup bound to a different
Browser
instance. java.awt.IllegalComponentStateException: component must be showing on the screen to determine its location
when movingJFrame
with invisible SwingBrowserView
component in it.java.lang.IllegalArgumentException
when callingBrowserView.setSize(0, 0)
.java.lang.OutOfMemoryError
on attempt to log an RPC request that contains a ~20MB string.- The
StartNavigationCallback.Params.url()
returning URL address without protocol when it should present. - Native crash when printing in
console.log()
oralert()
the property registered via theJsObject.putProperty()
method. - PDF file inside an
IFRAME
is opened in the whole view instead of opening in the frame on a web page. java.lang.NullPointerException
when closingBrowser
right after creating it.- The
Failed to register a ServiceWorker
error on a web page with JavaScript that works with Service Workers. java.lang.NoSuchMethodError: com.teamdev.jxbrowser.ui.internal.rpc.Bitmap.getPixels()Lcom/google/protobuf/ByteString;
when moving cursor over a web page in the JavaFXBrowserView
.- Some websites such as https://evernote.com not being loaded because of inability to use IndexedDB due
to
QuotaExceededError
.
We would like to thank you for all your feedback regarding using 7.0 and migrating from JxBrowser 6.x to 7! We really appreciate it!
Download JxBrowser 7.1
Please share your email with us, and we'll send you download instructions.
We were unable to send the email. Please use the direct link to download JxBrowser.
If you are a registered customer you don't need to do anything to use this update.
If you would like to evaluate the product, you need an evaluation license.
Follow @JxBrowserTeam to get notified of the library updates.
Subscribe to our RSS feed to get instant updates on new releases.