Bug 791911 - Listen for our child message managers dying and remove them from our list of managers to 'broadcast' to. r=gwagner
authorBlake Kaplan <mrbkap@gmail.com>
Tue, 02 Oct 2012 17:24:53 -0400
changeset 109209 0d5ac783d657439934525b0ae31851dd1f045930
parent 109208 5d0e0a533775956dc240b2661b9d9dba4aad9f3d
child 109210 139ec19e88be9ab4b111aaece91af6cef8590df7
push id82
push usershu@rfrn.org
push dateFri, 05 Oct 2012 13:20:22 +0000
reviewersgwagner
bugs791911
milestone18.0a1
Bug 791911 - Listen for our child message managers dying and remove them from our list of managers to 'broadcast' to. r=gwagner
dom/wifi/DOMWifiManager.js
dom/wifi/WifiWorker.js
--- a/dom/wifi/DOMWifiManager.js
+++ b/dom/wifi/DOMWifiManager.js
@@ -107,18 +107,16 @@ DOMWifiManager.prototype = {
     }
   },
 
   uninit: function() {
     this._onStatusChange = null;
     this._onConnectionInfoUpdate = null;
     this._onEnabled = null;
     this._onDisabled = null;
-
-    this._mm.sendAsyncMessage("WifiManager:managerFinished");
   },
 
   _sendMessageForRequest: function(name, data, request) {
     let id = this.getRequestId(request);
     this._mm.sendAsyncMessage(name, { data: data, rid: id, mid: this._id });
   },
 
   receiveMessage: function(aMessage) {
--- a/dom/wifi/WifiWorker.js
+++ b/dom/wifi/WifiWorker.js
@@ -1380,17 +1380,17 @@ function WifiWorker() {
   var self = this;
 
   this._mm = Cc["@mozilla.org/parentprocessmessagemanager;1"]
                .getService(Ci.nsIMessageListenerManager);
   const messages = ["WifiManager:getNetworks", "WifiManager:getKnownNetworks",
                     "WifiManager:associate", "WifiManager:forget",
                     "WifiManager:wps", "WifiManager:getState",
                     "WifiManager:setPowerSavingMode",
-                    "WifiManager:managerFinished"];
+                    "child-process-shutdown"];
 
   messages.forEach((function(msgName) {
     this._mm.addMessageListener(msgName, this);
   }).bind(this));
 
   Services.obs.addObserver(this, kMozSettingsChangedObserverTopic, false);
 
   this.wantScanResults = [];
@@ -1991,41 +1991,48 @@ WifiWorker.prototype = {
       }
     }
   },
 
   // nsIWifi
 
   _domManagers: [],
   _fireEvent: function(message, data) {
-    // TODO (bug 791911): Managers don't correctly tell us when they're getting
-    // destroyed, so prune dead managers here.
-    this._domManagers = this._domManagers.filter(function(obj) {
-      try {
-        obj.manager.sendAsyncMessage("WifiManager:" + message, data);
-        return true;
-      } catch(e) {
-        return false;
-      }
+    this._domManagers.forEach(function(manager) {
+      // Note: We should never have a dead message manager here because we
+      // observe our child message managers shutting down, below.
+      manager.sendAsyncMessage("WifiManager:" + message, data);
     });
   },
 
   _sendMessage: function(message, success, data, msg) {
     msg.manager.sendAsyncMessage(message + (success ? ":OK" : ":NO"),
                                  { data: data, rid: msg.rid, mid: msg.mid });
   },
 
   receiveMessage: function MessageManager_receiveMessage(aMessage) {
+    let msg = aMessage.data || {};
+    msg.manager = aMessage.target;
+
+    // Note: By the time we receive child-process-shutdown, the child process
+    // has already forgotten its permissions so we do this before the
+    // permissions check.
+    if (aMessage.name === "child-process-shutdown") {
+      let i;
+      if ((i = this._domManagers.indexOf(msg.manager)) != -1) {
+        this._domManagers.splice(i, 1);
+      }
+
+      return;
+    }
+
     if (!aMessage.target.assertPermission("wifi-manage")) {
       return;
     }
 
-    let msg = aMessage.json || {};
-    msg.manager = aMessage.target;
-
     switch (aMessage.name) {
       case "WifiManager:getNetworks":
         this.getNetworks(msg);
         break;
       case "WifiManager:getKnownNetworks":
         this.getKnownNetworks(msg);
         break;
       case "WifiManager:associate":
@@ -2036,49 +2043,28 @@ WifiWorker.prototype = {
         break;
       case "WifiManager:wps":
         this.wps(msg);
         break;
       case "WifiManager:setPowerSavingMode":
         this.setPowerSavingMode(msg);
         break;
       case "WifiManager:getState": {
-        let net = this.currentNetwork ? netToDOM(this.currentNetwork) : null;
         let i;
-        for (i = 0; i < this._domManagers.length; ++i) {
-          let obj = this._domManagers[i];
-          if (obj.manager === msg.manager) {
-            obj.count++;
-            break;
-          }
+        if ((i = this._domManagers.indexOf(msg.manager)) === -1) {
+          this._domManagers.push(msg.manager);
         }
 
-        if (i === this._domManagers.length) {
-          this._domManagers.push({ manager: msg.manager, count: 1 });
-        }
-
+        let net = this.currentNetwork ? netToDOM(this.currentNetwork) : null;
         return { network: net,
                  connectionInfo: this._lastConnectionInfo,
                  enabled: WifiManager.enabled,
                  status: translateState(WifiManager.state),
                  macAddress: this.macAddress };
       }
-      case "WifiManager:managerFinished": {
-        for (let i = 0; i < this._domManagers.length; ++i) {
-          let obj = this._domManagers[i];
-          if (obj.manager === msg.manager) {
-            if (--obj.count === 0) {
-              this._domManagers.splice(i, 1);
-            }
-            break;
-          }
-        }
-
-        break;
-      }
     }
   },
 
   getNetworks: function(msg) {
     const message = "WifiManager:getNetworks:Return";
     if (!WifiManager.enabled) {
       this._sendMessage(message, false, "Wifi is disabled", msg);
       return;