DESCRIPTION
-----------
Capturing a snapshot of WebView after it has finished loading a webpage behaves differently for `load` and `loadContent`.
PLATFORM
--------
Can be reproduced on MacOS Catalina, Ubuntu 18.04 and Windows 10 Using Oracle Java 8 (64-bit) and AdoptOpenJDK 11
FREQUENCY
---------
Can always be reproduced
STEPS TO REPRODUCE THE PROBLEM
------------------------------
1 Run the attached application
2 A file with name snapshot*.png is created in the temporary directory. It contains a blank image
3 Comment out L32 and uncomment L34. Run the application again
4 A new file with name snapshot*.png is created in the temporary directory. This contains the actual snapshot of the WebView
EXPECTED vs ACTUAL
------------------
EXPECTED
Both `WebView#load` and `WebView#loadContent` should show same behaviour
ACTUAL -
Capturing the snapshot of WebView by loading a webpage via:
* WebView#load: works fine
* WebView#loadContent: captures a blank page
---------- BEGIN SOURCE ----------
import javafx.application.Application;
import javafx.application.Platform;
import javafx.beans.value.ChangeListener;
import javafx.concurrent.Worker;
import javafx.embed.swing.SwingFXUtils;
import javafx.scene.Scene;
import javafx.scene.SnapshotParameters;
import javafx.scene.image.WritableImage;
import javafx.scene.web.WebView;
import javafx.stage.Stage;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.logging.Logger;
public class SnapshotRaceCondition extends Application {
private static final Logger log = Logger.getLogger(SnapshotRaceCondition.class.getName());
private static final String HTML_TEXT = "<html style='background-color: red;'><h1>TEST</h1></html>";
private static WebView webView = null;
@Override
public void start(Stage primaryStage) {
log.fine("Started JavaFX, creating WebView...");
primaryStage.setScene(new Scene(webView = new WebView()));
// JDK-8087569: Snapshot will not capture without showing stage
primaryStage.setOnShown(e -> {
webView.getEngine().loadContent(HTML_TEXT, "text/html");
// Uncomment this to see that it works fine when a url is provided instead of HTML text
// webView.getEngine().load("https://www.google.com");
});
// Add listener for SUCCEEDED
Worker<Void> worker = webView.getEngine().getLoadWorker();
worker.stateProperty().addListener(stateListener);
primaryStage.show();
}
/** Listens for a SUCCEEDED state to activate image capture **/
private static ChangeListener<Worker.State> stateListener = (ov, oldState, newState) -> {
if (newState == Worker.State.SUCCEEDED) {
WritableImage snapshot = webView.snapshot(new SnapshotParameters(), null);
final BufferedImage bufferedImage = SwingFXUtils.fromFXImage(snapshot, null);
try {
final Path snapshotFile = Files.createTempFile("snapshot", ".png");
ImageIO.write(bufferedImage, "png", snapshotFile.toFile());
} catch (IOException e) {
e.printStackTrace();
}
Platform.exit();
}
};
}
---------- END SOURCE ----------
-----------
Capturing a snapshot of WebView after it has finished loading a webpage behaves differently for `load` and `loadContent`.
PLATFORM
--------
Can be reproduced on MacOS Catalina, Ubuntu 18.04 and Windows 10 Using Oracle Java 8 (64-bit) and AdoptOpenJDK 11
FREQUENCY
---------
Can always be reproduced
STEPS TO REPRODUCE THE PROBLEM
------------------------------
1 Run the attached application
2 A file with name snapshot*.png is created in the temporary directory. It contains a blank image
3 Comment out L32 and uncomment L34. Run the application again
4 A new file with name snapshot*.png is created in the temporary directory. This contains the actual snapshot of the WebView
EXPECTED vs ACTUAL
------------------
EXPECTED
Both `WebView#load` and `WebView#loadContent` should show same behaviour
ACTUAL -
Capturing the snapshot of WebView by loading a webpage via:
* WebView#load: works fine
* WebView#loadContent: captures a blank page
---------- BEGIN SOURCE ----------
import javafx.application.Application;
import javafx.application.Platform;
import javafx.beans.value.ChangeListener;
import javafx.concurrent.Worker;
import javafx.embed.swing.SwingFXUtils;
import javafx.scene.Scene;
import javafx.scene.SnapshotParameters;
import javafx.scene.image.WritableImage;
import javafx.scene.web.WebView;
import javafx.stage.Stage;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.logging.Logger;
public class SnapshotRaceCondition extends Application {
private static final Logger log = Logger.getLogger(SnapshotRaceCondition.class.getName());
private static final String HTML_TEXT = "<html style='background-color: red;'><h1>TEST</h1></html>";
private static WebView webView = null;
@Override
public void start(Stage primaryStage) {
log.fine("Started JavaFX, creating WebView...");
primaryStage.setScene(new Scene(webView = new WebView()));
// JDK-8087569: Snapshot will not capture without showing stage
primaryStage.setOnShown(e -> {
webView.getEngine().loadContent(HTML_TEXT, "text/html");
// Uncomment this to see that it works fine when a url is provided instead of HTML text
// webView.getEngine().load("https://www.google.com");
});
// Add listener for SUCCEEDED
Worker<Void> worker = webView.getEngine().getLoadWorker();
worker.stateProperty().addListener(stateListener);
primaryStage.show();
}
/** Listens for a SUCCEEDED state to activate image capture **/
private static ChangeListener<Worker.State> stateListener = (ov, oldState, newState) -> {
if (newState == Worker.State.SUCCEEDED) {
WritableImage snapshot = webView.snapshot(new SnapshotParameters(), null);
final BufferedImage bufferedImage = SwingFXUtils.fromFXImage(snapshot, null);
try {
final Path snapshotFile = Files.createTempFile("snapshot", ".png");
ImageIO.write(bufferedImage, "png", snapshotFile.toFile());
} catch (IOException e) {
e.printStackTrace();
}
Platform.exit();
}
};
}
---------- END SOURCE ----------