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