Bug 777206 - SystemMessageInternal broadcasts information to all content processes [r=gwagner]
authorFabrice Desré <fabrice@mozilla.com>
Tue, 18 Sep 2012 10:34:56 -0700
changeset 107382 cf0512c87af743650f613a6e6f15a26485a0e65d
parent 107381 47825c36d6e8c141700931ce924fea316d51efd6
child 107383 fc624f71409d0779e522611e33c10f92759e4131
push id15005
push userfdesre@mozilla.com
push dateTue, 18 Sep 2012 17:35:30 +0000
treeherdermozilla-inbound@cf0512c87af7 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersgwagner
bugs777206
milestone18.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 777206 - SystemMessageInternal broadcasts information to all content processes [r=gwagner]
dom/messages/SystemMessageInternal.js
dom/messages/SystemMessageManager.js
--- a/dom/messages/SystemMessageInternal.js
+++ b/dom/messages/SystemMessageInternal.js
@@ -20,56 +20,73 @@ XPCOMUtils.defineLazyServiceGetter(this,
 let kMaxPendingMessages;
 try {
   kMaxPendingMessages = Services.prefs.getIntPref("dom.messages.maxPendingMessages");
 } catch(e) {
   // getIntPref throws when the pref is not set.
   kMaxPendingMessages = 5;
 }
 
-function debug(aMsg) { 
+const kMessages =["SystemMessageManager:GetPending",
+                  "SystemMessageManager:Register",
+                  "SystemMessageManager:Unregister"]
+
+function debug(aMsg) {
   //dump("-- SystemMessageInternal " + Date.now() + " : " + aMsg + "\n");
 }
 
 // Implementation of the component used by internal users.
 
 function SystemMessageInternal() {
   // The set of pages registered by installed apps. We keep the
   // list of pending messages for each page here also.
   this._pages = [];
+  this._listeners = {};
   Services.obs.addObserver(this, "xpcom-shutdown", false);
-  ppmm.addMessageListener("SystemMessageManager:GetPending", this);
+  kMessages.forEach((function(aMsg) {
+    ppmm.addMessageListener(aMsg, this);
+  }).bind(this));
 }
 
 SystemMessageInternal.prototype = {
   sendMessage: function sendMessage(aType, aMessage, aPageURI, aManifestURI) {
     debug("Broadcasting " + aType + " " + JSON.stringify(aMessage));
-    ppmm.broadcastAsyncMessage("SystemMessageManager:Message" , { type: aType,
-                                                                  msg: aMessage,
-                                                                  manifest: aManifestURI.spec });
+    if (this._listeners[aManifestURI.spec]) {
+      this._listeners[aManifestURI.spec].forEach(function sendMsg(aListener) {
+        aListener.sendAsyncMessage("SystemMessageManager:Message",
+                                   { type: aType,
+                                     msg: aMessage,
+                                     manifest: aManifestURI.spec })
+      });
+    }
+
     this._pages.forEach(function sendMess_openPage(aPage) {
       if (aPage.type != aType ||
           aPage.manifest != aManifestURI.spec ||
           aPage.uri != aPageURI.spec) {
         return;
       }
 
       this._processPage(aPage, aMessage);
     }.bind(this))
   },
 
   broadcastMessage: function broadcastMessage(aType, aMessage) {
     debug("Broadcasting " + aType + " " + JSON.stringify(aMessage));
     // Find pages that registered an handler for this type.
     this._pages.forEach(function(aPage) {
       if (aPage.type == aType) {
-        ppmm.broadcastAsyncMessage("SystemMessageManager:Message" , { type: aType,
-                                                                      msg: aMessage,
-                                                                      manifest: aPage.manifest });
-
+        if (this._listeners[aPage.manifest]) {
+          this._listeners[aPage.manifest].forEach(function sendMsg(aListener) {
+            aListener.sendAsyncMessage("SystemMessageManager:Message",
+                                       { type: aType,
+                                         msg: aMessage,
+                                         manifest: aPage.manifest})
+          });
+        }
         this._processPage(aPage, aMessage);
       }
     }.bind(this))
   },
 
   registerPage: function registerPage(aType, aPageURI, aManifestURI) {
     if (!aPageURI || !aManifestURI) {
       throw Cr.NS_ERROR_INVALID_ARG;
@@ -77,47 +94,73 @@ SystemMessageInternal.prototype = {
 
     this._pages.push({ type: aType,
                        uri: aPageURI.spec,
                        manifest: aManifestURI.spec,
                        pending: [] });
   },
 
   receiveMessage: function receiveMessage(aMessage) {
-    debug("received SystemMessageManager:GetPending " + aMessage.json.type + " for " + aMessage.json.uri + " @ " + aMessage.json.manifest);
-    // This is a sync call, use to return the pending message for a page.
     let msg = aMessage.json;
-    debug(JSON.stringify(msg));
+    switch(aMessage.name) {
+      case "SystemMessageManager:Register":
+        let manifest = msg.manifest;
+        debug("Got Register from " + manifest);
+        if (!this._listeners[manifest]) {
+          this._listeners[manifest] = [];
+        }
+        this._listeners[manifest].push(aMessage.target);
+        debug("listeners for " + manifest + " : " + this._listeners[manifest].length);
+        break;
+      case "SystemMessageManager:Unregister":
+        debug("Got Unregister from " + aMessage.target);
+        let mm = aMessage.target;
+        for (let manifest in this._listeners) {
+          let index = this._listeners[manifest].indexOf(mm);
+          while (index != -1) {
+            debug("Removing " + mm + " at index " + index);
+            this._listeners[manifest].splice(index, 1);
+            index = this._listeners[manifest].indexOf(mm);
+          }
+        }
+        break;
+      case "SystemMessageManager:GetPending":
+        debug("received SystemMessageManager:GetPending " + aMessage.json.type +
+          " for " + aMessage.json.uri + " @ " + aMessage.json.manifest);
+        // This is a sync call, use to return the pending message for a page.
+        debug(JSON.stringify(msg));
+        // Find the right page.
+        let page = null;
+        this._pages.some(function(aPage) {
+          if (aPage.uri == msg.uri &&
+              aPage.type == msg.type &&
+              aPage.manifest == msg.manifest) {
+            page = aPage;
+          }
+          return page !== null;
+        });
+        if (!page) {
+          return null;
+        }
 
-    // Find the right page.
-    let page = null;
-    this._pages.some(function(aPage) {
-      if (aPage.uri == msg.uri &&
-          aPage.type == msg.type &&
-          aPage.manifest == msg.manifest) {
-        page = aPage;
-      }
-      return page !== null;
-    });
+        let pending = page.pending;
+        // Clear the pending queue for this page.
+        // This is ok since we'll store pending events in SystemMessageManager.js
+        page.pending = [];
 
-    if (!page) {
-      return null;
+        return pending;
+        break;
     }
-
-    let pending = page.pending;
-    // Clear the pending queue for this page.
-    // This is ok since we'll store pending events in SystemMessageManager.js
-    page.pending = [];
-
-    return pending;
   },
 
   observe: function observe(aSubject, aTopic, aData) {
     if (aTopic == "xpcom-shutdown") {
-      ppmm.removeMessageListener("SystemMessageManager:GetPending", this);
+      kMessages.forEach((function(aMsg) {
+        ppmm.removeMessageListener(aMsg, this);
+      }).bind(this));
       Services.obs.removeObserver(this, "xpcom-shutdown");
       ppmm = null;
       this._pages = null;
     }
   },
 
   _processPage: function _processPage(aPage, aMessage) {
     // Queue the message for the page.
--- a/dom/messages/SystemMessageManager.js
+++ b/dom/messages/SystemMessageManager.js
@@ -138,16 +138,17 @@ SystemMessageManager.prototype = {
     return pendings[aType].length != 0;
   },
 
   mozHasPendingMessage: function sysMessMgr_hasPendingMessage(aType) {
     return this._getPendingMessages(aType, false);
   },
 
   uninit: function sysMessMgr_uninit()  {
+    cpmm.sendAsyncMessage("SystemMessageManager:Unregister", { });
     this._handlers = null;
     this._pendings =  null;
   },
 
   receiveMessage: function sysMessMgr_receiveMessage(aMessage) {
     debug("receiveMessage " + aMessage.name + " - " +
           aMessage.json.type + " for " + aMessage.json.manifest +
           " (" + this._manifest + ")");
@@ -172,16 +173,19 @@ SystemMessageManager.prototype = {
 
     let principal = aWindow.document.nodePrincipal;
     this._uri = principal.URI.spec;
 
     let appsService = Cc["@mozilla.org/AppsService;1"]
                         .getService(Ci.nsIAppsService);
     this._manifest = appsService.getManifestURLByLocalId(principal.appId);
     this._window = aWindow;
+    cpmm.sendAsyncMessage("SystemMessageManager:Register",
+                          { manifest: this._manifest });
+    debug("done");
   },
 
   classID: Components.ID("{bc076ea0-609b-4d8f-83d7-5af7cbdc3bb2}"),
 
   QueryInterface: XPCOMUtils.generateQI([Ci.nsIDOMNavigatorSystemMessages,
                                          Ci.nsIDOMGlobalPropertyInitializer]),
 
   classInfo: XPCOMUtils.generateCI({classID: Components.ID("{bc076ea0-609b-4d8f-83d7-5af7cbdc3bb2}"),