Extending an extension with a native app.

Usecase
I've recently come across a specific requirement from a customer who wanted a chrome extension  fiddling with the user machine file system. To be more specific, the addon was supposed to allow for the download of a cloud-based compressed file, decompress it and place the result in a specific directory for consumption by another application.
As many know, filesystem is sandboxed by chrome for security reasons and it is impossible per design to write files on the user machine outside of the control of the user.
I ended-up with a specific architecture outsourcing of the unauthorized job to a native app which bears none of the constraints a chrome extension does.

An elegant architecture
NativeMessaging Chrome API allows an extension to control - ie launch,communicate with and close - an external application:
  • Native application can be written in any language
  • An instance of the native app is launched when the extension connects to a configured service
  • Native app  receives messages on stdin and replies back to the addon by writing on stdout.
I elected javascript as the target language since it allows a single developer with limited language capacities like me to design the solution end2end.
The second biggest advantage is to benefit of all existing shareware libraries, in this particular case a compression/decompression library called jszip.

Implementation
After writing the first mockup of the addon/native app couple, I was able to get the solution to successfully work using a shellscript to launch nodejs with the native app js file as an argument.
Job was not completed however: I had to provide my customer with something "easily" deployable...

Electron
I write Electron apps and I love the ability of Electron to package javascript applications in standalone executables (that was the third motivation for electing javascript). Secondly, Electron is platform agnostic and able to generate an installer for Windows,Mac and Linux.
Unfortunately, the result is not that pretty: my native app once packaged is not receiving any message from the addon.After some googling, it appears to be a known problem (documented here), Electron is messing around with stdin/stdout and no solution is foreseen in a near future.

Workaround
With the idea of keeping Electron, I wrote a web-socket based communication (using nodejs-websocket) which does the job. However, the solution has a couple of drawbacks:
  • you need to pick an unused port number 
  • the port number needs to be  hand-managed :( across the potential multiple instances of the browser.

Making the bride more beautiful (as we say in french)
The only solution happens to get rid of Electron. I have not spent any effort yet on this, if you happen to know a simple alternative, please leave a comment. We will have a truly beautiful solution at that point !


Browser compatibility:
NativeMessaging API is also available in Firefox, please note there are a couple of minor implementation differences documented here.

PS: Here is a snippet for a native app including both web socket and the regular stdin/stdout communication schemes:

Comments

  1. Hello,Thank you very much for your article, but is there an example of a websocket connection?This is my Email 'huangkai361@gmail',looking forward to your reply.

    ReplyDelete
  2. Hello kavil, I have appended an example to the post !

    ReplyDelete

Post a Comment

Popular posts from this blog

Intercepting file download in chrome

Migrating to manifest v3