Bug 855556 - Stop sending contacts if the child process is dead. r=gwagner
authorReuben Morais <reuben.morais@gmail.com>
Tue, 23 Apr 2013 05:06:40 -0700
changeset 129575 2bd159c2257df6b195d5a11d31966eaffeaa260c
parent 129574 5a10c10a4a09f6579e7c30e5986527ea99171c8a
child 129576 5a62b421e490742fa54cff76c1d0d3380d355e3b
push id1
push userroot
push dateMon, 20 Oct 2014 17:29:22 +0000
reviewersgwagner
bugs855556
milestone23.0a1
Bug 855556 - Stop sending contacts if the child process is dead. r=gwagner
dom/contacts/fallback/ContactDB.jsm
dom/contacts/fallback/ContactService.jsm
--- a/dom/contacts/fallback/ContactDB.jsm
+++ b/dom/contacts/fallback/ContactDB.jsm
@@ -21,71 +21,82 @@ Cu.import("resource://gre/modules/Timer.
 const DB_NAME = "contacts";
 const DB_VERSION = 8;
 const STORE_NAME = "contacts";
 const SAVED_GETALL_STORE_NAME = "getallcache";
 const CHUNK_SIZE = 20;
 const CHUNK_INTERVAL = 500;
 
 function ContactDispatcher(aContacts, aFullContacts, aCallback, aNewTxn, aClearDispatcher) {
-  this.nextIndex = 0;
+  let nextIndex = 0;
+  let interval;
 
-  this.cancelTimeout = function() {
-    if (this.interval) {
-      clearTimeout(this.interval);
-      this.interval = null;
+  function cancelTimeout() {
+    if (interval) {
+      clearTimeout(interval);
+      interval = null;
     }
-  };
+  }
 
+  let sendChunk;
+  let count = 0;
   if (aFullContacts) {
-    this.sendChunk = function() {
-      if (aContacts.length > 0) {
-        aCallback(aContacts.splice(0, CHUNK_SIZE));
-        this.interval = setTimeout(this.sendChunk, CHUNK_INTERVAL);
-      } else {
-        aCallback(null);
-        this.cancelTimeout();
+    sendChunk = function() {
+      try {
+        if (aContacts.length > 0) {
+          aCallback(aContacts.splice(0, CHUNK_SIZE));
+          interval = setTimeout(sendChunk, CHUNK_INTERVAL);
+        } else {
+          aCallback(null);
+          cancelTimeout();
+          aClearDispatcher();
+        }
+      } catch (e) {
         aClearDispatcher();
       }
-    }.bind(this);
+    }
   } else {
     this.count = 0;
-    this.sendChunk = function() {
-      let chunk = [];
-      aNewTxn("readonly", STORE_NAME, function(txn, store) {
-        for (let i = this.nextIndex; i < Math.min(this.nextIndex+CHUNK_SIZE, aContacts.length); ++i) {
-          store.get(aContacts[i]).onsuccess = function(e) {
-            chunk.push(e.target.result);
-            this.count++;
-            if (this.count == aContacts.length) {
-              aCallback(chunk)
-              aCallback(null);
-              this.cancelTimeout();
-              aClearDispatcher();
-            } else if (chunk.length == CHUNK_SIZE) {
-              aCallback(chunk);
-              chunk.length = 0;
-              this.nextIndex += CHUNK_SIZE;
-              this.interval = setTimeout(this.sendChunk, CHUNK_INTERVAL);
+    sendChunk = function() {
+      try {
+        let chunk = [];
+        aNewTxn("readonly", STORE_NAME, function(txn, store) {
+          for (let i = nextIndex; i < Math.min(nextIndex+CHUNK_SIZE, aContacts.length); ++i) {
+            store.get(aContacts[i]).onsuccess = function(e) {
+              chunk.push(e.target.result);
+              count++;
+              if (count === aContacts.length) {
+                aCallback(chunk)
+                aCallback(null);
+                cancelTimeout();
+                aClearDispatcher();
+              } else if (chunk.length === CHUNK_SIZE) {
+                aCallback(chunk);
+                chunk.length = 0;
+                nextIndex += CHUNK_SIZE;
+                interval = setTimeout(this.sendChunk, CHUNK_INTERVAL);
+              }
             }
-          }.bind(this);
-        }
-      }.bind(this));
-    }.bind(this);
+          }
+        });
+      } catch (e) {
+        aClearDispatcher();
+      }
+    }
   }
 
-  this.sendChunk(0);
-}
+  sendChunk(0);
 
-ContactDispatcher.prototype = {
-  sendNow: function() {
-    this.cancelTimeout();
-    this.interval = setTimeout(this.sendChunk, 0);
-  }
-};
+  return {
+    sendNow: function() {
+      cancelTimeout();
+      interval = setTimeout(sendChunk, 0);
+    }
+  };
+}
 
 this.ContactDB = function ContactDB(aGlobal) {
   if (DEBUG) debug("Constructor");
   this._global = aGlobal;
 }
 
 ContactDB.prototype = {
   __proto__: IndexedDBHelper.prototype,
--- a/dom/contacts/fallback/ContactService.jsm
+++ b/dom/contacts/fallback/ContactService.jsm
@@ -109,17 +109,22 @@ let ContactService = {
           msg.options.findOptions);
         break;
       case "Contacts:GetAll":
         if (!this.assertPermission(aMessage, "contacts-read")) {
           return null;
         }
         this._db.getAll(
           function(aContacts) {
-            mm.sendAsyncMessage("Contacts:GetAll:Next", {cursorId: msg.cursorId, contacts: aContacts});
+            try {
+              mm.sendAsyncMessage("Contacts:GetAll:Next", {cursorId: msg.cursorId, contacts: aContacts});
+            } catch (e) {
+              if (DEBUG) debug("Child is dead, DB should stop sending contacts");
+              throw e;
+            }
           },
           function(aErrorMsg) { mm.sendAsyncMessage("Contacts:Find:Return:KO", { errorMsg: aErrorMsg }); },
           msg.findOptions, msg.cursorId);
         break;
       case "Contacts:GetAll:SendNow":
         // sendNow is a no op if there isn't an existing cursor in the DB, so we
         // don't need to assert the permission again.
         this._db.sendNow(msg.cursorId);