The one thing that jumps out at me is that you are using
createInstance on the JS and C++ sides. Unless you've done
something special in your C++ nsINotifService implementation to
have it only ever create one object, this code should have
created one nsINotifService object in the C++ code and one
different nsINotifService object in the JS code. I'm sure that's
not what you want.
You should use getService in the JS code and do_GetService in the
C++ code. This makes the xpcom service manager create (and hold)
one instance which will be given to anyone who asks for the
service again in the future.
John.
Chris Shen wrote:
>
> Hi guys,
>
> My browser application needs to receive a notification from javascript.
> I basically followed nsSample example. The way I did is that
> 1. create/implement a nsINotifListener, the interface like
> [scriptable, uuid(913C5060-A929-11d5-B85D-00105A69E379)]
> interface nsINotifListener : nsISupports
> {
> void notif(in string msg);
> };
>
> 2. create/implement a nsINotifService, the interface like
> [scriptable, uuid(5A0EC100-A928-11d5-B85D-00105A69E379)]
> interface nsINotifService : nsISupports
> {
> void addNotifListener(in nsINotifListener listener);
> void removeNotifListener(in nsINotifListener listener);
> void removeNotifListeners();
>
> void notif(in string msg);
> };
>
> the service has method
> NS_IMETHODIMP nsNotifService::Notif(const char *msg)
> {
> if(aListener)
> {
> aListener->Notif(msg);
> }
> return NS_OK;
> }
> which dispatches the notif to the listener.
>
> 3. create a component info, like
> static nsModuleComponentInfo components[] =
> {
> { "Notif Service",
> NS_NOTIFSERVICE_CID,
> NS_NOTIFSERVICE_CONTRACTID,
> nsNotifService::Create }
> };
> NS_IMPL_NSGETMODULE("nsNotifServiceModule", components)
>
> 4. build the notifservice as dll
>
> 5. create a test html page, like
> <html>
> <script language="javascript">
>
> netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
> var nserv =
> Components.classes["@mozilla.org/notifservice;1"].createInstance();
> nserv = nserv.QueryInterface(Components.interfaces.nsINotifService);
> dump("notifservice = " + nserv + "\n");
> function notif()
> {
>
> netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
> nserv.Notif("js notif");
> }
> </script>
> <form name="form">
> <input type="button" value="Get" onclick="notif();">
> <form>
> </html>
>
> 6. implement the browser app to subclass the listener interface and
> instantiate
> the notifservice on startup, like
> nsresult rv;
> notifserv = do_CreateInstance(NS_NOTIFSERVICE_CONTRACTID, &rv);
> if(NS_FAILED(rv))
> {
> return;
> }
> notifserv->AddNotifListener(p);
>
> I expect:
> At the runtime, my browser application loads the notifservice first and
> add itself as a listener to the service. By the time, I assume the
> notifservice
> remaining in memory. Then my browser app loads the test html page which
> loads
> the notifservice as well. Because the notifservice already registered in
> memory,
> I assume the xpconnect only increases the reference count rather than
> creates
> a new instance again. When I click the button in html, it will call the
> javascript function which in turn calls on the notifservice's method. The
> method
> dispatches the call to the listener.
>
> The browser app loads the notifservice and registeres itself as a listener
> successfully as I debug through but the it seems nothing happen at
> javascript side.
> The breakpoint never reaches nsNotifService's notif method. It seems tell me
> that
> loading the notifservice in js isn't successfully. I don't think I have to
> implement something like nsSample.js because I have c++ implemention, do I!?
> To instantiate a xpcom component and call on the component from javascript,
> what extra work should be done? Or, is the way I thought and did wrong?
> I have also searched the similar topics in the newsgroup against my
> implementation
> and didn't see any particular problem with my implementation.
> By the way, the "dump" js method didn't output to the debug console.
> What should be set in order to see some info in the console?
>
> Thanks