views:

258

answers:

6

How can I use the browser as a UI for a desktop app? The ways I have come up with so far are...

  1. Use all HTML/Javascript. Problem: Can't access filesystem or just about anything else.
  2. Run a local webserver while the application is in use. Problem: How do I kill it when the user is done? My users are not technical enough to Ctrl+C.
  3. Embed a browser component in a regular GUI. Problem: Embedded browser components tend to be glitchy at best. The support for Javascript/CSS is never as good as it is in a real browser.
  4. ...?

The ideal solution would work with any technology. I know there are options like writing Firefox extensions, but I want to have complete freedom in the backend technology and browser independence.

+1  A: 

In Windows, you could embed the IE ActiveX control, which uses the same rendering engine as IE. (That's a plus and a minus) You can set the ScriptObject property in your host code and access it in Javascript as window.external to do things that Javascript cannot do.

If you run a local webserver, you could have an exit link in the app that kills the websever.

SLaks
What I'm having trouble figuring out is how to write the kill link. I've come up with one solution, but it's very hacky. The servers I've been trying have all been Python, but any kind of concrete example would be cool.
Daniel Straight
And of course there's the problem that the user may not click the kill link.
Daniel Straight
If you host a WebBrowser control, you could kill the server when the host app exits. Otherwise, you could kill the server some time after the last request, and send heartbeats in your pages in case the user leaves it alone for a while. Or, you could just leave it running.
SLaks
I like the idea of sending heartbeats. I'm having trouble finding the off switch on any Python webserver though. They all seem to assume you would never want to kill the server in code.
Daniel Straight
I can't help you there. You could ask a separate question here.
SLaks
+1  A: 

You did not mention the OS you will need to target. But you might be able to create a program statared web server, then launced the default browser. Wait until the browser is terminated by the user and then shut down the web server.

So for example on windows you can use CreateProcess() to spawn the process then MsgWaitForMultipleObjects() to wait until it is finished executing.

Robert Love
OS independence would be fabulous as well, but Windows is what I'm working on. This seems like it could work. The user could still leave the browser open and use it for browsing other sites, but at least I know *eventually* it will get closed. There may be an issue though if the browser decides to open the app in a new tab rather than new browser. I think Firefox does this even when called from the command line.
Daniel Straight
If you wait for the browser to close, you'll never stop waiting. Remember that all modern browsers support tabs, so that many people, myself included, run a browser 24/7.
SLaks
Also, if the browser is already running, you won't even get a new process to wait on.
SLaks
... except on Google Chrome: each tab is a separate process.
jldupont
Yes, but I don't think that that separate process is the same one that you launched. (I could be wrong, though)
SLaks
If the server / parent program brings up a browser window for i/o it can then poll for the window's existence (eg. for enumWindows() { enumChildWindows()) } - this will work for tabs as well). No window? Pack up and go home. The server terminates when the tab is closed, the browser is closed or the machine is shut down.
mr calendar
+2  A: 

Please note that if you choose to run a local webserver, you're creating a security risk.

Any webpage running on the same machine that knows about your app can send requests to your server using Javascript, and you have no simple and reliable way of knowing what the request came from. (Don't trust the referer header)

Google Desktop, which uses a similar approach, has had several real-world vulnerabilities that allow any webpage to read any file on disk.

There are several ways to protect against this; I would recommend requiring each request to have a auth key which is randomly generated per-machine (and expires at some point), which you could put in the source for the actual pages. XHR protection would prevent malicious websites from reading the auth key, rendering them powerless.

SLaks
Can't the local server be set to only accept requests from the same machine it's running on?
Daniel Straight
Yes; I meant that Javascript on the same client could send such requests.
SLaks
Interesting....
Daniel Straight
Why does the XHR protection not prevent the requests in the first place? I'm not sure I'm completely understanding this here.
Daniel Straight
XHR prevents other pages from reading the responses, but not from sending requests. The level of vulnerability depends on what the requests do. I'm not sure how the Google Desktop vulnerability allowed attackers to read files, but I beleive it did.
SLaks
A: 

HTML Applications (HTA, for short) have been around for a while. You can read all about them here. They are basically HTML and Javascript with some extra options to create a window and with access to the local file system. They seem to be exactly what you want. It is Microsoft technology, so this will only work with IE on Windows systems. I've successfully used this as a front-end for a CD-ROM which was used to distribute software to first year students

Another option would be to use Adobe Air. I'm not all that familiar with the technology, but it seems to provide a framework to deploy web pages as desktop applications. I can't post a second link as a guest, but just google it and you'll find it soon enough.

Bas
Actually, this is exactly what I don't want, because "I want to have complete freedom in the backend technology and browser independence."
Daniel Straight
+2  A: 

If you are looking for a python Web Server with a Kill link, you could always check CherryPy.

import webbrowser
import cherrypy
import threading

class MyApp:
    """ Sample request handler class. """

    @cherrypy.expose
    def index(self):
        return """<html><head><title>An example application</title></head>
<body>
<h1>This is my sample application</h1>
Put the content here...
<hr>
<a href="/exit">Quit</a>
</body></html>"""

    @cherrypy.expose
    def exit(self):
        raise SystemExit(0)


class MyBGThread(threading.Thread):
    def __init__(self):
        threading.Thread.__init__(self)
        self.start()

    def run(self):
        cherrypy.tree.mount(MyApp())
        cherrypy.quickstart()

myThread = MyBGThread()
webbrowser.open("http://127.0.0.1:8080")

This code is based on the sample from the SingleClickAndRun on the cherrypy website: http://tools.cherrypy.org/wiki/SingleClickAndRun

Note than in a normal WebApp you would probably use a templating engine and load templates from methods like main.

Something that would be nice would be to embbed a browser control in a gui window and close the server when the app exits.

For the security, you could possibly add an authentication scheme. There are a few that are supported by cherrypy, but you possibly could implement your own too, using tool modules.

Martin
This is the kind of stuff I'm looking for. Thanks.
Daniel Straight
+1  A: 

I am looking to do the exact same thing (desktop app that uses an up to date HTML5 / CSS3 browser as the desktop app's GUI), only with Ruby (various reasons why I decided to work with Ruby). Its amazing the number of cross platform libraries people have come up with. But yet, few to no one, has done any work on trying to get a web browser to be a desktop app UI. Cross platform issue... well I won't say solved, but I will say several steps in the right direction taken.

To me this would be perfect with the new HTML5 / CSS3 standards coming out. I know it can be done with a web server running locally.

Another way might be like how the guys from “280 North” are doing what they do. They developed Objective-J (an extension of regular JavaScript that mimics how Objective-C extends regular C) and Cappuccino (the Objective-J equivalent of Objective-C’s Cocoa frame work on the MAC). They also developed “Atlas” which is 280 North’s version of Apple’s “Interface Builder” from Xcode, for their Objective-J and Cappuccino frameworks to build Internet Applications. Atlas is actually a Cappuccino web app running on your desktop as a desktop app. In this case they use the Narwhal… a cross platform, general purpose, JavaScript platform for developing JS apps outside of the browser (basically a specialized web server).

If any one can come up with an idea to make “Browser, direct connect to Desktop App” work without the need of a web server co-existing and still get to manipulate the local FS, I to would be very interested… Hmmm... Now that I think about it, I wonder if the new Google Chrome project “Native Client” can be used to do that. NaCL is much like Active X except you are not limited to a windows platform (but will be limited to the Google Chrome browser, at least for now). Only there is added security via Sandboxing, but you can manipulate the local FS… The more I think about it, the more I am beginning to suspect that it can be done.

Any thoughts?

Brad Hutchins