XPCOM Component Written in Java

Derrick Rice <[email protected]> Fri, 23 Jan 2009 14:16:04 -0800 (PST)
Newsgroups gmane.comp.mozilla.devel.java
Organization http://groups.google.com
Message-ID <95649b9c-6b94-4077-a8dd-9a2874b71f49@e24g2000vbe.googlegroups.com>
I've also posted this to the mozswing mailing list, since that's what
I'm using.  But this seems to be a core XPCOM problem I'm having.

Let me just say that this I am not looking to start a VM from
mozilla... my entire application is java, with mozilla used via JNI
(mozswing/JavaXPCOM).  What I want to know is why my components cannot
be directly access by the javascript, yet they seem to interact in
other ways.

------------------------------------------

What is so confusing is that I see the javascript
successfully interacting with the java, but as soon as I attempt to
explicitly call a function, it falls.

Goal: Create a new XPCOM component which will be written in Java and
installed in my mozswing application.  Use it from javascript.

Steps and results:

1. Create a new interface idl and compile it into an *.xpt and java
interface. [OK]
2. On mozswing initialization, install a factory for this interface
that will generate java objects.  This is no different than how I've
installed java factories for other already existing interfaces.[OK]
3. After installing the factory, add the component to the "JavaScript
global property" category, so that it is accessible to website
javascript. [OK]
4. Since the interface extends nsIClassInfo and my component (which I
generate in the factory) can also queryInterface to
nsISecurityCheckedComponent, I can allow it to be used from the web
page.

*** At this point I can successfully create and invoke my component
through XPCOM with JAVA:
XPCOMUtils.create("<contract id>", myInterface.class).callFunction()

5. Generate a test HTML page with javascript that accesses the item
[This is where things go bad]

var instance = window.myComponent.QueryInterface
(Components.interface.nsIMyNewInterface);
alert(instance);             // yields [xpconnect wrapped
nsIMyNewInterface]
alert(instance.member);           // yields the value of the member
alert(instance.callFunction);             // yields function
callFunction() { [native code] }
instance.callFunction();        // generates an error, see below

[Exception... "Component returned failure code: 0x80004001
(NS_ERROR_NOT_IMPLEMENTED) [nsIMyNewInterface.callFunction]"
nsresult: "0x80004001 (NS_ERROR_NOT_IMPLEMENTED)"  location: "JS frame
:: webpage.html :: run :: line 15"  data: no]

If I throw print statements into my java component, I see it being
access (QueryInterface is called and so are the
nsISecurityCheckedComponent functions).  This indicates to me that
it's clearly possible for the javascript to communicate with the java.
 It's already taking place when I call QueryInterface.  But if I try
to call something else, it fails.

Am I running into a natural limitation of JavaXPCOM?  How can I
communicate back to my existing java application from javascript
XPCOM?

Problems solved:
* accessing XPCOM from javascript
* installing XPCOM factories from java
* making components visible and accessible to webpages

Problems existing:
* using my components from javascript

I saw someone else had this problem but saw no solution:
http://osdir.com/ml/mozilla.devel.java/2006-01/msg00007.html

Again, any help here would be seriously appreciated.  Even if it's
just a little insight.