Monitoring plugins

Summary

A new component of the plugin system is now available to measure how long it takes plugins (e.g., Adobe Flash) to execute their calls. This component then reports the plugin runtime using the observer service to anyone registered to receive the notifications. This article discusses how developers can make use of this new feature.

Runtime Data

The runtime information reported is always in fractions of a second. Because the component measures the wall clock time it takes for blocking plugin calls to execute, the value includes both CPU time, the wait time between allocation of CPU time to the process as well as any disk I/O time. It is therefore technically incorrect to say that the runtime is a measure of CPU use, however, it is a good representation of overall resources being consumed by the plugin.

Usage

To make use of the new component you must register to receive its runtime notifications using the observer service. The notification's topic is experimental-notify-plugin-call. If you are new to the Mozilla observer service, you may want to familiarize yourself with it before proceeding further. You can find more information on the observer service here and here.

Below are a number of JavaScript snippets that would be useful to developers trying to use this feature:

Registration

To register for runtime notifications with the observer service you must create a class with an observe method which receives 3 parameters (subject, topic and data) as well as a register method that contains the following code:

var observerService = Components.classes["@mozilla.org/observer-service;1"]
                        .getService (Components.interfaces.nsIObserverService);
observerService.addObserver(this, "experimental-notify-plugin-call", false);

Observing

As discussed above, to specify what you want done when a notification arrives your class must have an observe method, receiving 3 parameters (subject, topic and data). The topic contains the notification's topic - experimental-notify-plugin-call in this case, the data is the runtime in milliseconds and the subject is always null and should not be used.

Here is an example that shows the runtime in an alert box to the user if the runtime exceeds half a second in length:

 observe: function(subject, topic, data) {	
   if (topic == "experimental-notify-plugin-call" ) {
     if (data > 0.500) {
       alert("Runtime is: " + data);
     }
   }
 }

NOTE: This is just a simplified example and the use of alert() is discouraged as the component can send hundreds of notifications each second and could potentially cause your browser to crash if an excessive number of alert boxes are displayed.

Also note that in the example above an if statement first checks to see that the arriving notification's topic is the correct one. This is useful in cases where your class is registered to receive notifications for more than one topic with the observer service.

Clean Up

To unregister your class with the observer service - when you no longer want to be listening to runtime notifications - your class must include an unregister method that contains the following code:

var observerService = Components.classes["@mozilla.org/observer-service;1"]
                       .getService(Components.interfaces.nsIObserverService);
observerService.removeObserver(this, "experimental-notify-plugin-call");

Skeleton Observer Class

Below is a skeleton class that you may use to listen to runtime notifications:

 function PluginObserver() {
   this.registered = false;
   this.register();	//takes care of registering this class with observer services as an observer for plugin runtime notifications
 }

 PluginWatcherObserver.prototype = {
   observe: function(subject, topic, data) {	

     if (topic == "experimental-notify-plugin-call") //In case your class is registered to listen to other topics
       //This gets executed each time a runtime notification arrives
       // --YOUR CODE GOES HERE--
     }


   },
   //Takes care of registering the observer services for the "experimental-notify-plugin-call" topic
   register: function() {
     if (this.registered == false) { //This check prevents double registration -- something you want to avoid!!
       var observerService = Components.classes["@mozilla.org/observer-service;1"]
                                       .getService(Components.interfaces.nsIObserverService);
       observerService.addObserver(this, "experimental-notify-plugin-call", false);
       this.registered = true;
     }
   },
   //Unregisters from the observer services
   unregister: function() {
     if (this.registered == true) {
       var observerService = Components.classes["@mozilla.org/observer-service;1"]
                                       .getService(Components.interfaces.nsIObserverService);
       observerService.removeObserver(this, "experimental-notify-plugin-call");
       this.registered = false;
     }
   }
 }

Additional Resources

More information on the observer service: