How does the Listener get instantiated?.  I have setup the following methods
and included the Javascript routines you mentioned - but the Listener does
not get instantiated in order to start the whole process.

Patrick McHale
Powerlan USA


NS_IMETHODIMP
JSListener::ConnectionOpened(PRBool success)
{
     nsCOMPtr<mynamespaceNotifier> notifier = do_CreateInstance
(NS_JSWEBTERM_CONTRACTID);
     mynamespaceListener* aConnectionListener;
     notifier->GetConnectionListener(&aConnectionListener);
     aConnectionListener->ConnectionOpened(success);

 return NS_OK;
}



NS_IMETHODIMP
JSNotifier::GetConnectionListener(mynamespaceListener *
*aConnectionListener)
{
 *aConnectionListener = mListener;
 return NS_OK;
}



NS_IMETHODIMP
JSNotifier::SetConnectionListener(mynamespaceListener * aConnectionListener)
{
 mListener = aConnectionListener;

    return NS_OK;
}

"John Bandhauer" <[EMAIL PROTECTED]> wrote in message
[EMAIL PROTECTED]">news:[EMAIL PROTECTED]...
> Patrick McHale wrote:
> >
> > Thanks you for your reply - this is the way we wish to proceed and will
try
> > to implement this. Our problem is that we wish to implement this
> > dynamically - so that we do not have to hard code our function names
within
> > the C++ code.
> >
> > We would like to pass our javascript function names somehow in the
future.
> > In the mean time we have decided to hard code the javascript function
names.
>
> You saw Sean Echevarria's answer to your question in the plugins
> group, right? If you are doing a plugin and can go that route
> then great. Else your callback would need to implement an xpcom
> interface in order to use xpconnect to make the call...
>
> >
> > A question I would like to ask - When the interfaces are declared to
send /
> > receive callbacks - are these using separate uuid numbers. Does this
mean
> > that I will need to use guidgen to generate a couple more numbers to
place
> > in the new component interfaces?.
>
> Yes, you'd be declaring interfaces with new iids and shipping an
> xpt file and all that. I assume that you'd already be declaring
> your interface on which you are going to call your
> "theSession.OpenConnection" method. It is the callback's
> interface you'd need to add.
>
> >
> > Also if convenient - could you explain more about doing an AddRef on the
> > current Listener and using the nsCOMPtr class member. I am
> > unsure about this. Is there some information around regarding nsCOMPtr.?
> > What is this used for?
>
> The idea is simply that your JS code is going to be passing an
> object pointer into the C++ code. If that C++ code is going to
> hold onto that pointer for later use then it must add a reference
> on that pointer to hold it in place and then release the
> reference when it is done with the pointer. This is standard COM
> stuff. The nsCOMPtr template class makes this easier (once you
> get up to speed using it). There is a manual...
>
> http://www.mozilla.org/projects/xpcom/nsCOMPtr.html
>
> John.
>
> >
> > With Thanks
> >
> > Patrick McHale
> > Powerlan USA
> >
> > "John Bandhauer" <[EMAIL PROTECTED]> wrote in message
> > [EMAIL PROTECTED]">news:[EMAIL PROTECTED]...
> > > When using xpcom you are encouraged to think in terms of
> > > interfaces and objects rather than callback functions -
> > > regardless of the programming language you use.
> > >
> > > So the 'normal' way to do something like this is...
> > >
> > > // Declare the interface to receive callbacks
> > > [scriptable, uuid(...)]
> > > interface mynamespaceListener : nsISupports
> > > {
> > >   void connectionOpened(in PRBool success);
> > > };
> > >
> > > // Declare the interface that will send callbacks.
> > > // You need to be able to tell it who to call...
> > > [scriptable, uuid(...)]
> > > interface mynamespaceNotifier : nsISupports
> > > {
> > >   // You could use explicit get/set.
> > >   // But attributes are easier...
> > >   attribute mynamespaceListener connectionListener;
> > > };
> > >
> > > You implemenent the get/set methods of mynamespaceNotifier and do
> > > an AddRef on the current listener (an nsCOMPtr class member is
> > > good for this).
> > >
> > > You expose that notifier object ot JS either as a service or more
> > > directly by whatever means..
> > >
> > > Your JS code then creates a JS object that has a connectionOpened
> > > method and passes that object to the notifier object by setting
> > > the notifier's connectionListener property.
> > >
> > > There are pleny of styles of doing this, but you might do is
> > > something like this...
> > >
> > > var listener = {
> > >   connectionOpened : function(success) {
> > >     if (success)
> > >       alert("The Connection was made!")
> > >     else
> > >       alert("The Connection Failed.");
> > >   }
> > >   // you can add whatever other properties you might want to this
> > > object
> > > };
> > >
> > > // assuming that your notifer is a service...
> > > var clazz = Components.classes["my_notifier_contractid"];
> > > var iface = Components.interfaces.mynamespaceNotifier;
> > > var notifier = clazz.getService(iface);
> > >
> > > notifier.connectionListener = listener;
> > >
> > > Now in your C++ code you can just call something like...
> > >   mListener->ConnectionOpened(PR_TRUE);
> > > ...and the call will be routed to the JS code.
> > >
> > > Note that if you really implement this object in a document then
> > > you'd probably want to clear the listener then the page gets
> > > unloaded. e.g....
> > >   notifier.connectionListener = null;
> > > This ought to make your C++ code Release the previous listener
> > > and will cause xpconnect to allow the JS object to be garbage
> > > collected when there are no other references to it.
> > >
> > > I hesitate to tell you about it... but if you absolutely *need*
> > > the JS code to be called back as a plain function rather than as
> > > a method on an object then you *could* use some xpconnect
> > > functionality that was very recently added to support legacy DOM
> > > event handling. I discourage its use - there is no support for
> > > doing this in any other language. The pattern is...
> > >
> > > // Declare the interface to receive callbacks
> > > // ... using the 'function' keyword
> > > [function, scriptable, uuid(...)]
> > > interface mynamespaceListener : nsISupports
> > > {
> > >   void connectionOpened(in PRBool success);
> > > };
> > >
> > >
> > > In JS you can use a plain function..
> > >
> > > function WebTerm_ConnectionOpened(success)
> > > {/*...*/}
> > >
> > > The C++ code is the same.
> > >
> > > You set the callback using:
> > > notifier.connectionListener = WebTerm_ConnectionOpened;
> > >
> > > When the call is made to the callback xpconnect will notice that
> > > this is a [function] interface and attempt to call the object as
> > > a function rather than lookup a named function property on the
> > > object and call that as it would normally do.
> > >
> > > Note that there is *no* support for...
> > >
> > > notifier.connectionListener = "WebTerm_ConnectionOpened()";
> > >
> > > This would imply that xpconnect would need to know how to convert
> > > a string into a compiled function. It does not do that. The DOM
> > > supports this using a bunch of specialized code.
> > >
> > > Again, I *really* encourage you to use objects with named methods
> > > which make the object meet the requirements of the declared
> > > interface rather than use the less supported [function] hack.
> > >
> > > Also, I just looked at your example below again and realized that
> > > I showed you a more generic "set it and forget it" listener
> > > pattern. For the specific case you have you could do pretty much
> > > what I wrote above, but just declare your OpenConnection method
> > > to take an 'in' param of type mynamespaceListener and pass your
> > > listener object into the function as a param. Be sure to AddRef
> > > and Release the interface pointer appropriately on the C++ side.
> > >
> > > Also, you may have noticed xpidl's method name leading character
> > > upper-casing rules. the deal is that we have history of using
> > > LeadingUpperCaseMethods in C++ and leadingLowerCaseMethods in
> > > JavaScript. If got decided (with *much* controversy!) a while
> > > back to encourage people to declare their interfaces like:
> > > "myMethod" in the idl and the C++ header mapping will get
> > > "MyMethod" and the JS will use "myMethod". the xpidl compiler,
> > > xpconnect and other such dynamic mapping layers deal with making
> > > this work right. So anyway, you are encouraged to use the
> > > "myMethod" style in your idl method and attribute names.
> > >
> > > John.
> > >
> > > Patrick McHale wrote:
> > > >
> > > > Hi,
> > > >
> > > > I was wondering about implementing CallBacks - Calling Javascript
> > functions
> > > > from an XPCOM object. I am not sure about how to correctly implement
> > this.
> > > > At present I have a Javascript function which I wish to call.
> > > >
> > > > function WebTerm_ConnectionOpened(success) {
> > > > if (success)
> > > >       alert("The Connection was made!")
> > > > else
> > > >       alert("The Connection Failed.");
> > > > }
> > > >
> > > > I also have a function defined to intiate the open connection - with
a
> > > > Callback function description.
> > > >
> > > > function OpenConnection(theSession) {
> > > >     theSession.OpenConnection(true, 300
,"WebTerm_ConnectionOpened()");
> > > >
> > > > The open connection routine works fine - but would like to get the
> > CallBack
> > > > operation working.  How should the IDL file be setup?.  Is this to
be
> > > > defined as a inout attribute?.  What is the return parameter needed
to
> > > > enable a Callback function to work?.
> > > >
> > > > Would be very grateful for some input on this.
> > > >
> > > > Regards
> > > >
> > > > Patrick McHale
> > > > Powerlan USA



Reply via email to