As an intermediate proof-of-technology step, I'm trying to do an
immediate callback to my js object, and this is failing. My apologies
for the length of this, but I figured it's better to give too much info
than too little.... A question or two is at the end of all this...
I've declared a new interface:
[scriptable, uuid(8FC0AAA9-3C3F-4377-8179-6EA50E7A8286)]
interface nsIPhishListener : nsISupports
{
void onLookupComplete(in nsICancelable aRequest,
in long aResult);
};
to go with my existing object (plus the asynch request):
[scriptable, uuid(EE5AA2A0-B27F-4e73-A62C-CA7A4E8201DC)]
interface IFFHook : nsICancelable
{
:
:
nsICancelable AsyncLookupPhish(in AUTF8String aHostName,
in nsIPhishListener aListener);
};
My js code, lifted and modified from a post elsewhere:
var listener =
{
QueryInterface : function(aIID)
{
alert("js: myListener: QueryInterface(" + aIID + ")\n");
if (aIID.equals(Components.interfaces.nsIPhishListener) ||
aIID.equals(Components.interfaces.nsISupports) )
{
alert("js: myListener: QueryInterface : ok\n");
return this;
}
throw Components.results.NS_NOINTERFACE;
Components.returnCode =
Components.results.NS_ERROR_NO_INTERFACE;
return null;
},
onLookupComplete: function( aRequest, aResult )
{
alert("js: myListener: onLookupComplete(" + aRequest + ", " +
aResult +")\n");
}
}
function MyComponentTestGo() {
try {
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect")
;
const cid =
"@siteadvisor.com/SiteAdvisor/FFHook;1";
obj = Components.classes[cid].createInstance();
obj =
obj.QueryInterface(Components.interfaces.IFFHook);
} catch (err) {
alert(err);
return;
}
alert("js: Before AsyncLookupPhish");
obj.AsyncLookupPhish("www.siteadvisor.com", listener);
alert("js:After AsyncLookupPhish");
}
And the pertinent C++ header and source:
class CFFHook : public IFFHook
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSICANCELABLE
NS_DECL_IFFHOOK
CFFHook();
private:
~CFFHook();
protected:
void ReportComplete();
nsCOMPtr<nsIPhishListener> m_Listener;
------------------
NS_IMETHODIMP CFFHook::AsyncLookupPhish(const nsACString & aHostName,
nsIPhishListener *aListener, nsICancelable **_retval)
{
::MessageBox(NULL, _T("C++: AsyncLookupPhish 1"), _T("Foo"),
MB_OK);
m_Listener = aListener;
::MessageBox(NULL, _T("C++: AsyncLookupPhish 2"), _T("Foo"),
MB_OK);
// DEBUG DEBUG
ReportComplete();
return NS_OK;
}
void CFFHook::ReportComplete()
{
CString sz;
::MessageBox(NULL, _T("C++: Before OnLookupComplete"),
_T("Foo"), MB_OK);
nsresult nr = m_Listener->OnLookupComplete(this, 42);
sz.Format(_T("C++: OnLookupComplete returned %08X"), nr);
::MessageBox(NULL, sz, _T("Foo"), MB_OK);
m_Listener = NULL;
}
The QI on my object gets called for nsISupports guid by (I presume) FF's
XPCOM framework at the point of the "obj.AsyncLookupPhish" call, but
never again. I would have expected a QI call at the "m_Listener =
aListener;" assignment.
Then, the "OnLookupComplete" callback returns the not-so-helpful
0x80004005 (NS_ERROR_FAILURE), and no surprise, the js onLookupComplete
is not called.
Do I have to do some magic to register my new nsIPhishListener with
XPCOM, beyond putting the generated xpt into FF's component directory
and clearing the xpti and compreg files in my profile?
However, the C++ call that's supposed to be invoking the method on the
JavaScript object is returning with 0x80004005 (NS_ERROR_FAILURE).
Clearly, I'm getting into the XPCOM dispatch code, but it's not relaying
into my JS object.
What can cause this nondescript failure code?
--- snip ---
Also am I right in assuming that all the JS code is privileged? (In
that case you don't need the enablePrivilege call).
Nickolay
>
> --- snip ---
> _______________________________________________
> dev-tech-xpcom mailing list
> dev-tec...@lists.mozilla.org
> https://lists.mozilla.org/listinfo/dev-tech-xpcom
>
Unfortunately, I don't have the background to answer your question about
the priviledge issue; I copied the test js from elsewhere.
Have you looked in the error console for interesting error info?
If XPConnect were having difficulty calling your method then you
should expect it to likely return a more interesting nsresult than the
generic failure code.
Your JS obj is not going to get as many QI calls as you expect.
XPConnect will try a QI for nsISupports to establish object identity
in some cases. But, inasmuch as JS objects are not even required to
implement QI, the fact that your object is not QI'd for your special
interface is not telling. XPConnect *trusts* you when you pass the
object as an instance of your interface. It builds a wrapper to
represent that interface for you and hands it to your C++ code.
I'm pretty sure that nsCOMPtr assignment does not require a QI call in
the normal case either. It is assigning typed pointers and doing ref
counting only.
John.
My callback function is so far just a placeholder:
onLookupComplete: function( aRequest, aResult )
{
alert("js: myListener: onLookupComplete(" + aRequest + ", " + aResult
")\n");
}
.. so yeah, I *think* I'd know if it got called back. :-)
(I just tried wrapping the alert in a try/catch block, and it still
didn't get called. I also called the function directly, and I did get
the alert.)
Thanks for the info on the QI behavior, I've been doing COM for so long
I've come to expect things in XPCOM that don't necessarily hold.
And to reveal more of my newbie-ness: how do I open the error console in
FireFox?
Thanks!
-Paul
-----Original Message-----
From: dev-tech-xp...@lists.mozilla.org
[mailto:dev-tech-xp...@lists.mozilla.org] On Behalf Of John
Bandhauer
Sent: Monday, December 04, 2006 3:30 PM
To: dev-tec...@lists.mozilla.org
Subject: Re: XPCOM cpp to js callback
John.
and you should read this:
http://kb.mozillazine.org/Setting_up_extension_development_environment#Set_development_prefs
Nickolay
Anyway, I've sprinkled a lot of alert() calls in the js, and a bunch of
MessageBox in my C++, and they're all getting called (except for the one
that says my callback was called from C++).
-----Original Message-----
From: Nickolay Ponomarev [mailto:asqu...@gmail.com]
Sent: Monday, December 04, 2006 3:51 PM
To: Schmidt, Paul
So? Only preferences which are actually currently set are in about:config.
That preference is not set by default; when it _is_ set, it has an effect. Just
set it in about:config.
> dump() seems to be a no-op.
Without setting browser.dom.window.dump.enabled it will be.
-Boris
So add it.
> it also refers to the -console flag, which gets a
> complaint in the error log.
And still works. The message in the console is a known bug.
> toJavaScriptConsole() is not defined,
It is defined in browser.xul overlays. Where is it mentioned?
> and dump() seems to be a no-op.
>
Not if you run with -console and actually enable the said pref.
You need to set the prefs and check if there's anything interesting in
the JS console.
Nickolay
-----Original Message-----
From: dev-tech-xp...@lists.mozilla.org
[mailto:dev-tech-xp...@lists.mozilla.org] On Behalf Of Boris
Zbarsky
Sent: Monday, December 04, 2006 4:11 PM
To: dev-tec...@lists.mozilla.org
Subject: Re: XPCOM cpp to js callback
Paul_S...@McAfee.com wrote:
> That setup page seems out of date, at least for my FF version 2.0: It
> mentions browser.dom.window.dump.enabled which is not in my
> about:config
So? Only preferences which are actually currently set are in
about:config.
That preference is not set by default; when it _is_ set, it has an
effect. Just
set it in about:config.
> dump() seems to be a no-op.
Without setting browser.dom.window.dump.enabled it will be.
-Boris
The only output there was what I put in a dump() call. No other warning
or error messages were generated by my attempt at calling back my
object.
So is this any more useful than alert(), beyond the message having
persistence?
-----Original Message-----
From: dev-tech-xp...@lists.mozilla.org
[mailto:dev-tech-xp...@lists.mozilla.org] On Behalf Of Schmidt,
Paul
Sent: Monday, December 04, 2006 3:45 PM
To: jband_...@rattlebrain.com; dev-tec...@lists.mozilla.org
Subject: RE: XPCOM cpp to js callback
It's definitely still loaded, I'm doing this in a very simple test page
w/o any navigation or anything, and a subsequent JS alert is popping up
as expected.
My callback function is so far just a placeholder:
onLookupComplete: function( aRequest, aResult )
{
alert("js: myListener: onLookupComplete(" + aRequest + ", " + aResult
")\n");
}
.. so yeah, I *think* I'd know if it got called back. :-)
(I just tried wrapping the alert in a try/catch block, and it still
didn't get called. I also called the function directly, and I did get
the alert.)
Thanks for the info on the QI behavior, I've been doing COM for so long
I've come to expect things in XPCOM that don't necessarily hold.
And to reveal more of my newbie-ness: how do I open the error console in
FireFox?
Thanks!
-Paul
-----Original Message-----
From: dev-tech-xp...@lists.mozilla.org
[mailto:dev-tech-xp...@lists.mozilla.org] On Behalf Of John
Bandhauer
Sent: Monday, December 04, 2006 3:30 PM
To: dev-tec...@lists.mozilla.org
Subject: Re: XPCOM cpp to js callback
John.
As for my privilege question, why does the code in MyComponentTestGo
run? Is it in a script for a chrome:// document? Or is it just a
webpage? Do you have to click through a security dialog before the
code gets to run?
Nickolay
On 12/5/06, Paul_S...@mcafee.com <Paul_S...@mcafee.com> wrote:
> Ok, I have a console.
>
> The only output there was what I put in a dump() call. No other warning
> or error messages were generated by my attempt at calling back my
> object.
>
> So is this any more useful than alert(), beyond the message having
> persistence?
>
>
>
> -----Original Message-----
> From: dev-tech-xp...@lists.mozilla.org
> [mailto:dev-tech-xp...@lists.mozilla.org] On Behalf Of Boris
> Zbarsky
> Sent: Monday, December 04, 2006 4:11 PM
> To: dev-tec...@lists.mozilla.org
> Subject: Re: XPCOM cpp to js callback
>
> Paul_S...@McAfee.com wrote:
> > That setup page seems out of date, at least for my FF version 2.0: It
> > mentions browser.dom.window.dump.enabled which is not in my
> > about:config
>
> So? Only preferences which are actually currently set are in
> about:config.
> That preference is not set by default; when it _is_ set, it has an
> effect. Just
> set it in about:config.
>
> > dump() seems to be a no-op.
>
> Without setting browser.dom.window.dump.enabled it will be.
>
> -Boris
I would suggest that you confirm that there are no stale descriptions
of the interface on your system; e.g. previous attempts at the
interface using different UUIDs or names or method signatures. If the
typelib loader finds an xpt file that is not in sync with the idl that
is compiled into your component then odd things can happen. Also, make
sure your UUIDs are unique and not used by some other interface. These
are the sorts of problems that can come up as code evolves during
development. It is worth being sure that this is not what is going on
here.
The only other idea that comes to mind right now is something that may
not be very attractive to you as a component developer. But, if *I*
was trying to solve this problem then I'd use a debug build of the
browser and then trace into the call that your C++ component makes. It
*should* get into nsXPCWrappedJSClass::CallMethod. And from there lots
of fun stuff might happen.
Other than that, I don't know what to tell you. The general thing it
sounds like you are trying to do certainly works elsewhere. Perhaps
there is some subtle thing wrong with your code or your 'setup' that
is not obvious from here. Either figure out a way to debug it or
experiment with variations that might give you a clue to what thing
you might be doing wrong.
John.
________________________________
From: Nickolay Ponomarev [mailto:asqu...@gmail.com]
Sent: Mon 12/4/2006 8:06 PM
To: Schmidt, Paul
________________________________
From: dev-tech-xp...@lists.mozilla.org on behalf of John Bandhauer
Sent: Mon 12/4/2006 8:18 PM
To: dev-tec...@lists.mozilla.org
Subject: Re: XPCOM cpp to js callback
John.
You could also just try adding a method with no params to the callback
interface, implement it in JS, and try calling that. i.e. get
*something* working and then figure out what is different about what
doesn't work.
John.
________________________________
From: dev-tech-xp...@lists.mozilla.org on behalf of John Bandhauer
Sent: Tue 12/5/2006 1:36 PM
To: dev-tec...@lists.mozilla.org
Subject: Re: XPCOM cpp to js callback
John.
John.
John.
> interface IFFHook : nsICancelable
it'd be best for the protection of your object if it was iffIHook or
something where iff is any lowercase pair or tripple of letters, the I
is an I and the Ho is Caps followed by Lower.
> nsICancelable AsyncLookupPhish(in AUTF8String aHostName,
idl methods and attributes really should be declared interCaps not
InitialCaps.
> QueryInterface : function(aIID)
for debugging it's a good idea to name your functions (then you can try
using venkman without being as confused, among other tools)
strange:
> throw Components.results.NS_NOINTERFACE;
unreachable code:
> Components.returnCode =
> Components.results.NS_ERROR_NO_INTERFACE;
that confuses people
> return null;
> obj = Components.classes[cid].createInstance();
> obj =
> obj.QueryInterface(Components.interfaces.IFFHook);
you should combine those as:
> obj = Components.classes[cid].createInstance(Components.interfaces.IFFHook);
>
Don't use MessageBox, it's *dangerous*. Seriously. (read about
windbgdlg to understand why, but in short you're likely to get your app
killed.)
> ::MessageBox(NULL, _T("C++: AsyncLookupPhish 1"), _T("Foo"),
> MB_OK);
Instead use NS_DebugBreak or nsDebug::whatever or something in that
family.
> The QI on my object gets called for nsISupports guid by (I presume) FF's
> XPCOM framework at the point of the "obj.AsyncLookupPhish" call, but
> never again. I would have expected a QI call at the "m_Listener =
> aListener;" assignment.
Note that you really really really really should not be defining
components from dom. they should be written as js components that live
in a components directory. such components do not have DOM globals at
all (and are therefore safer for use as callbacks). This means no
access to window.alert and friends. Use Components.utils.reportError or
whatever to send a message to the Error Console.
At the very least, it'd be good to know where your js component lives
(chrome/, components/).
I'm sorry that I'm jumping in late. So many newsgroups....
Nickolay was trying fairly hard to tell you about tools>error console
be sure that this (hidden pref!) is set to true:
javascript.options.showInConsole
but more seriously, you want to install and enable venkman (and be sure
to configure it to debug chrome!)
Using an html file is really not a good idea. You're much better off
using a component from the start. You can actually use
Components.manager.nsIComponentRegistrar.autoRegister(xpcom_local_file_object)
to register new objects on the fly, so you could really go through 20
iterations w/o restarting (although I *really* wouldn't recommend it).
instead of thinking twice. just don't do it :|.
it's against a modern xpcom law to extend someone else's interface
(excluding nsISupports). Extending them tends to result in some really
bad multiple inheritance. (The classic example involves
nsIBrowserHistory3 or something, really not a pretty sight.)
[I say modern because when jband was originally working on gecko we
weren't very explicit about saying don't do it. we've now learned that
being explicit about don'ts is important :(]