javascriptdom-eventsxpcom

Notifying JavaScript of external event from XPcom


I have been trying to find a solution to what seems to be relatively simple scenario. I have JavaScript running in an html page that makes a call to an XPcom that I have written in C++. So far, so good.

This XPcom retrieves a reference to the observer-service (do_GetService("@mozilla.org/observer-service;1")); fires a notify which is 'seen' by the JavaScript; the XPcom creates a windows thread (AFX), passes a copy of the observer-service reference and returns to the JavaScript caller; expecting the XPcom thread to send additional notifies at appropriate times (based on external events).

The notifies however fail to arrive in the JavaScript and my initial thought was the notify method will not deliver notifications from a 'different' thread. I've used the VStudio debugger to confirm the program sequence is as expected; ie the external event is being received by the thread and the notify method is being called... but, no notify event arrives.

I've read quite a few postings across the web and nothing really 'nails' the particular scenario I'm trying to address. I'm not married to the idea of using notify:

The objective is quite simple. deliver asynchronous events or notifications from an XPcom thread to the main, or even sub, thread of the JavaScript; but, I'm getting less than 10% traction here. Has anyone accomplished this, or have ideas as to how to get it done?


Solution

  • You are correct, the observer service works only on the main thread (check the return value of your Notify() call, it should be NS_ERROR_UNEXPECTED). You are also correct as far as the solution goes - dispatch an event to the main thread, via NS_DispatchToMainThread(). As to the actual implementation, function NS_NewRunnableMethod() should help (unless you want to create your custom nsIRunnable implementation - e.g. to pass parameters). You probably want to do something like this:

    nsCOMPtr<nsIRunnable> event = NS_NewRunnableMethod(xpcomComponent, &nsMyComponent::processEvent);
    nsresult rv = NS_DispatchToMainThread(event);
    

    Here xpcomComponent would be a reference to your XPCOM component instance and nsMyComponent::processEvent its method that needs to be called on main thread. That method would then be able to notify the observer.