On Feb 19, 2006, at 3:49 PM, Aleksandar Vasilev wrote:
I am looking for a simple method of calling a javascript function from C++. XPConnect is too heavy for implementing just a simple function call. Currently I'm doing it by opening a javascript: URL. Generally, what are the "lightweight" ways for interacting with javascript?
Thanks in advance

Please don't laugh:

In DTV (www.participatoryculture.org), a xulrunner-based application written in Python and bits of JS and C, we decided to put an "air gap" between the Mozilla-based frontend (and the JS in it) and the Python/C backend. At first we tried to make direct XPCOM calls (eg, create a Javascript XPCOM object that exposes an 'execJS' method, instantiate it in an appropriate context as a service, and call the method from C++ or PyXPCOM as you would any other XPCOM method) but we had a lot of weird deadlock problems apparently involving the JS UI thread that we didn't have the expertise to resolve, so we switched to this simpler approach.

The backend ("embedding application" if you prefer) runs a very simple in-process HTTP server that listens on 127.0.0.1. The page loaded in the browser contains Javascript that uses XMLHttpRequest to open an asynchronous connection to this server. There is a Mozilla- specific extension to XMLHttpRequest that allows a "multipart" flag to set, whereupon the server can return a "multipart/x-mixed-replace" document and push a series of document parts across the connection. When each part is received, the registered XMLHttpRequest callback is called with the part that just arrived. We just push a series of Javascript expressions across the connection, and make the callback evaluate the expression that was just received.

(Likewise, when the browser wants to trigger an action in the application, it makes an XMLHttpRequest to the same in-process HTTP server with the action in the query string or in the request body.)

Simple, easy to understand/analyze, effective, uses only code paths in Mozilla that have been thoroughly exercised in Firefox.

The HTTP server can be very simple. If you don't care about security (not a policy I encourage) and aren't using the server for anything else, you just need to kick off a thread that calls socket(), bind(), listen(), accept(), maybe call read() until you see a blank line, and then calls write() as necessary to send Javascript to execute, putting the right headers on each block of Javascript as per link below. And you need to smuggle the port number of the server into your document somehow.

The one wrinkle is that Mozilla will deny your XMLHttpRequest as an insecure cross-site request unless your document was also loaded from http://127.0.0.1, or you turn off the same-origin security policy by giving your script the UniversalBrowserRead flag. (Careful with that!) Yes, this is true even if your document was loaded from a file: URL. However, documents loaded from chrome: URL's are exempt. (But then how are you going to get the port number into it? Well, we do it with a call to a Python-implemented XPCOM object which returns the port number. If you don't know how to implement XPCOM objects in C ++, you might do it by setting a pref in C++, and having the chrome document read that pref from JS.)

For more on the Mozilla's 'multipart/x-mixed-replace'-based server push technology, google for "multipart/x-mixed-replace" or see:
http://www.xulplanet.com/tutorials/mozsdk/serverpush.php [start here]
http://wp.netscape.com/assist/net_sites/pushpull.html

If you (or anyone) wants to implement this and has questions, drop me a line and I'm happy to try to help.

Geoff Schmidt
Participatory Culture Foundation
[EMAIL PROTECTED]

_______________________________________________
dev-embedding mailing list
[email protected]
https://lists.mozilla.org/listinfo/dev-embedding

Reply via email to