List icon Contents

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');

Learn more

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();

Learn more

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() and blur() 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 the Element 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:

i18n

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 the browsercore processes created by the killed Java process.
  • Update the details of the browsercore.exe process on Windows.
  • XPathResult.asSingleNode() returns an empty Optional instead of throwing exception when the node was not found.
  • Default implementations of the StartDownloadCallback for both Swing and JavaFX BrowserView 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 always ENGLISH_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 moving JFrame with invisible Swing BrowserView component in it.
  • java.lang.IllegalArgumentException when calling BrowserView.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() or alert() the property registered via the JsObject.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 closing Browser 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 JavaFX BrowserView.
  • 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.

Sending...
Please check your inbox.

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.

Get free 30-day trial