I have a Chrome Native Messaging Host application writed in Java 8, running on MacOS, that uses SunPKCS11 to read digital certificates from a cryptographic USB token.
String providerConfig = "name = OpenSC1\nlibrary = /usr/local/lib/libcastle.1.0.0.dylib\nslot=1\n";
ByteArrayInputStream localByteArrayInputStream = new ByteArrayInputStream(providerConfig.getBytes());
SunPKCS11 pk11provider = new SunPKCS11(localByteArrayInputStream);
When instantiating the provider (last line) the onDisconnect event on the Chrome extension fires and chrome.runtime.lastError.message shows:
Error when communicating with the native messaging host.
My guess at the moment is that the underlying token driver API is writing something to stdout, which is the communication channel between the Chrome extension and the Native Messaging Host. This violates the communication protocol and causes the connection between those two to end. The jar itself keeps running just fine and further code can even read the digital certificate data.
I've been trying to block stdout writing when instantiating the provider but I can't find a way to do so. I've already tried overriding stdout with an empty PrintStream with EVERY method overrided
System.setOut(new PrintStream(System.out) {
@Override
public void write(int b) {
logger.info("write");
}
... every other method
}
but the API seems to be ignoring the overriding and uses the default stdout anyways. I've tried executing the jar from the Terminal and it is indeed printing a lot of things to the console (things that seems to be about reading from the usb token).
So I need to either block (or redirect) the SunPKCS11 instantiation output, or somehow tell the Chrome extension to ignore my jar stdout for some time (I can modifiy the Chrome extension code).
In the end I isolated the code section that calls de system API to a new jar file, and from my main app I invoke that jar. By doing that all the uncontrolled writing to the standard output is done in a different scope and is not read by my Chrome Extension.
ProcessBuilder pb = new ProcessBuilder("java", "-jar", "segementedProcess.jar");
pb.redirectError(outFile);
pb.redirectOutput(outFile);
Process p = pb.start();
p.waitFor();
It's far from a pretty solution but it works.
I am updating the question title to be more related to the solution I used.