how to communicate with a desktop application from browser? - javascript

Is it possible to communicate with a desktop application from browser?
I want to do something like this,
Let's say there is a button in my web application with a URL to a data source and when button is clicked desktop application opens and get that data source URL and process data with desktop application.
Is it difficult to do such thing? Any examples?

On windows its trivial to create a custom URL Protocol that's invokable via
..
This works in IE, FF and Chrome, although in the latter the link must be opened via javascript to avoid omni-bar confusion.

You will need to have something running on the deskop, like a server, and make a request to it for the server to open up an application. You could do it with a Node.js. Of course that requires the server to be running on the client's desktop.
The alternative would be to make a browser extension / plugin, and have people install that. Those extensions could probably launch an application on the desktop.

You can easily add Fleck WebSocket server to your desktop application, and then access this using Websocket.
Note: Only Windows 8 and 10 support WebSockets through Microsoft's WebSockets implementation, but Fleck will work with Windows 7.
https://github.com/statianzo/Fleck
It's quite easy to add Fleck to your project using NuGet Package Manager:
Install-Package Fleck
Here is the echo example from Fleck webpage (add this to the C# program to execute during startup):
var server = new WebSocketServer("ws://127.0.0.1:8181");
server.Start(socket =>
{
socket.OnOpen = () => Console.WriteLine("Open!");
socket.OnClose = () => Console.WriteLine("Close!");
socket.OnMessage = message => socket.Send(message);
});
In the javascript:
var exampleSocket = new WebSocket("ws://127.0.0.1:8181", "protocolOne");
exampleSocket.send("Here's some text that the server is urgently awaiting!");
//and receive (make a listener for the socket) :
exampleSocket.onmessage = function (event) {
console.log(event.data);
}

Hm, you need something like client-server application. The server is a lightweight http server, which is waiting for messages from the client (browser). The browser can communicate with your server via ajax for example.

Here is a clunky suggestion, but I think worth mentioning all the options since the custom URI and running server solutions are pretty involved... Generate a small file containing the parameters of interest, with a custom extension associated with your desktop app. So when the user clicks the browser button they will have to go through the browser's file download dialog/toolbar and maybe some annoying security verification popups... not ideal user experience, but might be the easiest way to implement this type of communication, and doesn't require a process running in the background like a server.
I have a web app used within my company for interfacing to old databases and poorly organized files. I need a way to allow the users to open the actual files from the network and not download copies, so they can be edited in place. Considering a solution like this or the custom URI scheme so that a small executable not running in the background can simply be passed the filename and open it for the user directly.

the desktop application should embed a small server in it, like Jetty. Since the browser content source domain (e.g. www.myDomain.com) is different than the localhost domain of the Jetty, you would run into security problems. These should be overcome by the use of CORS (Cross Origin Resource Sharing) which is a new standard. Using CORS, the Jetty server tells the browser that it/localhost allows Cross domain access to its resources if the requests originate from the source domain www.myDomain.com. For security reasons, i would also make the Jetty reject any request whose source ip is not localhost

In addtion to Alex K's answer for windows... for those looking for solution on macOS and Linux.
Linux
Most of the modern distros implement freedesktop standards and one of them is desktop files. You can create a desktop file with [service]
section.
$ cat test.desktop
[Desktop Entry]
Version=1.0
Terminal=false
Type=Application
Comment=My test app
Name=TestApp
Icon=TestIcon
Exec=/opt/test/test.sh %u
DBusActivatable=true
Categories=Network;
MimeType=x-scheme-handler/test; <------ This is handler for test://somedata URLs
NoDisplay=false
Copy this file in /usr/share/applications/test.desktop
macOS
Simply add something like following in your applications Info.plist file
<array>
<dict>
<key>CFBundleTypeIconFile</key>
<string>/tmp/test.png</string>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
<key>CFBundleURLName</key>
<string>com.mytest</string>
<key>CFBundleURLSchemes</key>
<array>
<string>test</string> <---- This is handler for test://somedata URLs hit on browser
</array>
</dict>
</array>

Related

Is there an easy reliable way to transfer a file over local network using Electron / Node.js / terminal?

Are there any built-in methods in Electron / Node.js allowing to transfer a file over local network to another device?
I want to be able to send files locally from one computer to another (through an Electron app), but I also want it to be able to send files to smartphones.
How do I do it? Is it possible to just create a temp local server and download the file from another device by opening the URL (e.g. 192.168.0.x:x/file.txt)?
I tried using https://www.npmjs.com/package/quick-transfer which does exactly that, but for some reason opening the link on another device doesn't do anything.
As painful as it is for me to suggest... I'd recommend WebRTC for this, for these reasons:
It will make a local connection, when possible.
It will work over the internet as well, if required.
You can work around any firewall difficulties with TURN.
You will have compatibility with browsers.
You won't be opening up some server to a file that anyone on the network can get... transmission occurs over a secured connection. (This doesn't mean you can ignore other security aspects in your application however!)
Sample code: https://webrtc.github.io/samples/src/content/datachannel/filetransfer/
Commentary: It's amusing to me that in 2018, we still haven't solved the problem of sending a file from point A to point B. Network Neighborhood in Windows was the golden age, and now it's all screwed up with this newfangled cloud crap. :-) Obligatory: https://xkcd.com/949/

Embedded Devices - Javascript Debugging

I work on embedded devices but am not able to install any software on them (e.g. programs like gdbserver are out). I need to monitor javascript events on those browsers. For example, if we run a web app on the EWB, the device it's on might have a keyboard pop-up. I need a way to see what triggers this event.
I am thinking along the lines of perhaps embedding something into the HTML or javascript that automatically reports any events back to a workstation somewhere.(I already have logs, but they are not live and it's difficult to pinpoint what happens - even beartailing them... wish I could have something like Firebug, but since it's embedded I can't)
Has anyone seen anything along those lines?
To get a debug connection to a web app or page running on a remote device:
Install vorlon using npm
Download ngrok
Start the vorlon server, the server port will probably be localhost:1337 and the following steps assume this
From a terminal/command prompt run ngrok with ngrok http 1337 and it should report an ip address for the other end of the tunnel, something like def01234.ngrok.io available via http and https.
Instead of the local script tag which vorlon suggests, use the remote ngrok address, e.g. <script src="https://def01234.ngrok.io/vorlon.js"></script>. ngrok exposes both http and https - as this is over the public internet I would strongly recommend using a secure connection.
Log onto the vorlon server on your local machine.
If the above test works you are going to want to do two more things:
Get an account at ngrok (or an alternative secure tunnel service) to get a fixed address.
Configure vorlon authentification according to the instructions on this page. By default it is insecure so ANYBODY with the exposed ngrok address could log onto the dashboard and mess with your embedded devices.

How to create a simple WebSocket Server in Chrome App?

I'm trying to develop a Chrome App that will work together with a Chrome Extension that I already created, wherein the Chrome Extension will send information to the Chrome App.
For this communication I thought use the WebSocket locally, in Chrome Extension I managed to make the Client, but now I'm having difficulty in creating the Server in the Chrome App, because I wanted to make as simple as possible without having to install something beyond of the Chrome App.
Among the first Google results there is a sample app from Chrome team: Http WebSocket Server.
You've got to understand that making a server in Chrome Apps is difficult; you are given access to a raw socket, and you need to fully implement the protocol that a particular server must use. Even a HTTP server is non-trivial, WebSockets is even less so.
So: it's possible, but it's not simple unless you're using an existing library.
Just to add to the accepted answer:
There is a Chrome Extension already in the Chrome Web Store: Web Server for Chrome.
And it is opensource: GitHub Link. You can use it as a library to your Chrome App.
Cheers!

How may a web page that is loaded via https connect to a WebSocket server running on localhost?

I'm trying to create a web page that can connect to a client-local WebSocket server. The idea is to use the JavaScript client running in the browser as kind of a proxy to enable communication between the remote web server and the locally installed client application which implements the WebSocket service.
So basially, what I'd do is load a web page from https://example.com which includes some JavaScript that opens a new WebSocket to ws://localhost:1234/context.
This works fine as long as the web page is accessed via http. As soon as https is used, however, Firefox and Internet Explorer refuse to connect and the WebSocket constructor throws an exception (SecurityError, code 18).
Now, I already found advice from Mozilla stating that https sites should only use secure (wss://) WebSockets and plain http sites should only use plain WebSockets (link). But I don't really see the security issue when connecting to localhost from within an https context. Besides, this works like a charm for Chrome, Opera and Safari.
So the actual question is: Is there any way to work around this issue? Like introducing a non-https context inside the web page or something similar to get all browsers to connect to ws://localhost from within a https-delivered web page?
Thanks a lot in advance! I'm not exactly a web developer so this kind of browser-specific behaviour isn't really in my fields of expertise :)
You have to accept the cert first.
You can do this by simply going to https://localhost:1234/context, in your case. Once that's done, you can use the wss URL in your question.

Can the OS as well as javascript/HTML5 access localstorage?

I would like to read the browser's "localstorage" when the browser is off using the OS !
I want to save client data in localstorage and then switch off the browser and the internet and then let an OS program (a windows exe) access and analyse that data and then write new data into that localstorage area so that when the browser restars the new data is in localstorage.
This should be possible because my OS (i.e. windows) can read can delete cookies from the browser "files" ... so presumably once i know the format of the localstorage "file" then the OS is boss of all of its files and so it should be able to alter them !
So: how do i read and write to JavaScript/HTML5/DOM "localstorage" using "client side .exe programs" ?
FAILING THAT: is there any other way that the OS can pass simple data into (and out of) the browser ?
Obviously all of this has both huge potential POWER and huge potential DANGER !
The browser can only become the "virtual OS of the future" if the real OS can interact safely with it !!
Thank You.
Of course an app running locally with the appropriate permissions can access any file on disk. However, the real question is what to do with that file once it's open?
Consider the following:
Each browser (Chrome, Firefox, IE, Opera) is likely to store localstorage data in its own proprietary format. You'd have to reverse engineer those formats.
Since those formats are an implementation detail (not a documented API), they are liable to change. This will break your app and/or corrupt user data.
What happens if you modify those data files while the browser is open (even if the page in question isn't open)? The browsers don't expect their data files to change out from underneath them, so it's likely you'd see strange behavior.
All of this is to say that this is a very bad idea. You're messing with the internals of someone else's application; that's a big no-no.
Have you considered an alternative approach? When I was faced with a similar problem, I simply implemented a very simple HTTP server in my app that was bound to a specific port on 127.0.0.1.
With XHR and the appropriate CORS headers, your browser-based application can communicate with your desktop app in a safe manner.
Here are some other ways:
Embed a web browser control in your application. The web browser control can readily peek into the page, and the page can readily peek into the local storage. The web browser control refers chiefly to Internet Explorer.
You can pass parameters from the web page into an initiated executable (even a batch file) by manipulating the name of the executable. (Use application/bat as Content-Type to invite the OS to run your program when the user downloads it.)
A ClickOnce program initiated from the browser can readily receive data from the webpage.
You can use automation in your program (AutoIt, AutoHotKey) to copy/paste to an from a field on your web page. You can find the window by title as you control the title on the web page side. You can even automate opening a browser, navigating it to a page that dumps the local storage into a text field, and focuses the field.
ActiveX controls (good luck)
I can't speak for similar tricks for OS X or Linux.

Categories

Resources