Global Notifications

This section will describe the observer service which can be used to send notifications to any objects that are interested.

Sending Notifications

Sometimes, for large applications, you will want to communicate with other parts of your application. For instance, to notify an application component that a particular task is complete. You could notify the components directly, but that would mean that you would need to change your code whenever a new notification needs to be sent or received.

The observer service can handle this for you. A component can register with the observer service for a given topic, identified by a string name. Later, another component can signal that topic, and the observer service will call all of the components that have registered for that topic.

The observer service implements the nsIObserverService interface, and is used to register and unregister observers. The observers implement the nsIObserver interface, and are responsible for responding when a particular topic is triggered.

The observers are registered globally, meaning that they are kept available until they are either unregistered or the application exits. Note that closing the window the observer was created in does not necessarily remove it. Thus, you only need to register an observer once and it will be called even when the component is no longer using it. For this reason, you need to be careful to ensure that an observer is not registered multiple times, and that you remove it when you no longer need it.

The observer service has an addObserver method which can be used to add an observer:

var observerService =
  Components.classes["@mozilla.org/observer-service;1"]
    .getService(Components.interfaces.nsIObserverService);
observerService.addObserver(observer,"my-topic",false);

First, the observer service is retrieved using the getService method. The addObserver method takes three arguments. The first is the observer object, which implements the nsIObserver interface. This will be defined below. The text "my-topic" is the topic to listen to. When that topic is triggered, any observers that have been registered for that topic will be invoked. The final argument indicates whether the observer service should hold a weak reference to the observer. If false, the service will hold a strong reference, ensuring that the observer is not deleted or garbage collected until it is explicitly removed from the observer service. If true, however, it might be deleted when no other references to the observer exist except from the observer service.

Above, we use false for the third argument, which will cause the observer to be called until we remove it or Mozilla exits. If it was true, the observer would likely be removed when the script that added it was unloaded.

We can remove an observer using the removeObserver function:

observerService.removeObserver(observer,"my-topic");

The two arguments are similar to the addObserver function. Note that it is possible to have an observer listen to several topics by calling addObserver multiple times.

To signal the observers of a topic, use the service's notifyObservers method. Calling this method will signal all registered observers of a given topic. Here is an example:

observerService.notifyObservers(subject,"my-topic","add");

The first argument should be any XPCOM object. This will be passed to the observers for additional information about why you are signaling them. The second argument is the topic. The third argument is a string, which can be any value. The third argument, like the subject, supplies additional information. The subject and data are not used by the observer service directly -- they are just extra values you can pass to the observers. For example, if you wanted to send a "Download Complete' notification, the subject might be a download object, and the data string might be the URL downloaded. Either value may be null if you don't need them.

The nsIObserver interface has only a single method named observe. Observers you create will need to implement this method. It will be called when the topic is signaled. For example:

var observer = {
  observe: function(subject,topic,data){
    alert("Topic sent: " + topic);
  }
};

The arguments to the observe function are the same as with the observer service's notifyObservers function. In this example, an alert is displayed showing the topic that was sent.

Built-in Topics Used by Mozilla

The following table lists some of the topics that Mozilla uses for various purposes. You can always create your own by using a different topic name. It is recommended that you use a topic name that is unique, for example by including the application title, for topics that are specific to your application.

There are also a number of topics that are too application-specific so they are omitted from the table below.

Topic Subject Data Details
quit-application None None Called when the application is exiting. Listen for this topic to perform cleanup on exit.
xpcom-shutdown the nsIServiceManager None Called when the application is exiting. Listen for this topic to perform cleanup on exit. Unlike the 'quit-application' topic, it may be too late to perform some tasks as services have already shutdown.
xpcom-autoregistration the nsIServiceManager A string that indicates what has been registered. Called when a component is registered or unregistered.
memory-pressure an nsIMemory object Either 'low-memory', 'alloc-failure', 'heap-minimize' This is called when memory is low so that observers can free resources and do garbage collection and the like. It can also be called when the heapMinimize method of an object that implements nsIMemory is called.
perm-changed an nsIPermission The string 'added', 'changed', 'deleted' or 'cleared' (cleared means all permissions are removed) A cookie or image loading permission has been changed. For example, this topic would be sent when the user selects to block an image.
profile-approve-change an nsIProfile either "startup" or "switch" or application startup and a profile change request respectively. Called to indicate that a request has been made to select a different user profile. You can reject the change by calling vetoChange of the nsIProfileChangeStatus interface which is implemented by the profile passed as the subject.
profile-before-change an nsIProfile either "startup" or "switch" or application startup and a profile change request respectively. On shutdown, this will be either 'shutdown-cleanse' or 'shutdown-persist'. Called to indicate that the currently selected user profile is about to change. This is also called on application exit so the observers may save settings before exiting.
profile-after-change an nsIProfile either "startup" or "switch" or application startup and a profile change request respectively. Called to indicate that the currently selected user profile has changed.
prefservice:before-read-userprefs the nsIPrefService None Called before the user preferences are read.
prefservice:before-reset the nsIPrefService None Called before the user preferences are reset.
domwindowopened an nsIDOMWindow (which is the same as a JavaScript window object) None Sent whenever a new window is opened. The is sent after the window has already opened.
domwindowclosed an nsIDOMWindow (which is the same as a JavaScript window object) None Sent whenever a window is closed.
network:offline-about-to-go-offline the nsIIOService The string 'offline' Called just before offline mode is enabled
network:offline-status-changed the nsIIOService Either 'online' or 'offline' depending on the new state Called after offline mode is either enabled or disabled
http-on-modify-request an nsIHttpChannel None Called just before an HTTP request is made. The subject contains the channel which can be modified, for example, to set additional headers. (Newer Mozilla builds only - older builds may use nsIHttpNotify)
http-on-examine-response an nsIHttpChannel None Called when an HTTP response is available which can be modified by using the nsIHttpChannel passed as the subject. (Newer Mozilla builds only - older builds may use nsIHttpNotify)
Add a note User Contributed Notes
September 30, 2005, 2:18 am asqueella at gmail dot com
There's also "quit-application-requested" notification, fired in globalOverlay.js canQuitApplication() (the line number may be a bit different), during which you can cancel the quit.

Another notification is "quit-application-granted", fired after all "quit-application-requested" observers allow the quit.
June 16, 2005, 5:13 am example at example dot com
Two other global notifications dealing with components:
xpcom-startup and app-startup; these (I think the second is preferred, at least for services) can be used to launch a component. To receive them, add to your nsIModule.registerSelf :

var catMan = Components.classes["@mozilla.org/categorymanager;1"]
.getService(Components.interfaces.nsICategoryManager);
catMan.addCategoryEntry("app-startup", "MyComponent",
MYCOMP_CONTRACTID, true, true);

For a service, that would be:

catMan.addCategoryEntry("app-startup", "service",
MYCOMP_CONTRACTID, true, true);

This must be paired in unregisterSelf with a:

catMan.deleteCategoryEntry("app-startup", MYCOMP_CONTRACTID, true);

Copyright © 1999 - 2005 XULPlanet.com