Bug 1023695 - Part 5: Notify deleted info after DB has been changed. r=vyang, a=2.0+
authorBevis Tseng <btseng@mozilla.com>
Fri, 27 Jun 2014 13:28:10 +0800
changeset 208924 775ba85429bc47f991db632694ecd9731de7103c
parent 208923 bf117b204a28b71fca3d02563fcc7347061ea96d
child 208925 6dd0fbb7c2e5d2eac8536589de3ba01b6fc35832
push id494
push userraliiev@mozilla.com
push dateMon, 25 Aug 2014 18:42:16 +0000
treeherdermozilla-release@a3cc3e46b571 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersvyang, 2
bugs1023695
milestone32.0a2
Bug 1023695 - Part 5: Notify deleted info after DB has been changed. r=vyang, a=2.0+
dom/mobilemessage/src/gonk/MmsService.js
dom/mobilemessage/src/gonk/MobileMessageDB.jsm
--- a/dom/mobilemessage/src/gonk/MmsService.js
+++ b/dom/mobilemessage/src/gonk/MmsService.js
@@ -32,20 +32,20 @@ const kSmsSendingObserverTopic          
 const kSmsSentObserverTopic              = "sms-sent";
 const kSmsFailedObserverTopic            = "sms-failed";
 const kSmsReceivedObserverTopic          = "sms-received";
 const kSmsRetrievingObserverTopic        = "sms-retrieving";
 const kSmsDeliverySuccessObserverTopic   = "sms-delivery-success";
 const kSmsDeliveryErrorObserverTopic     = "sms-delivery-error";
 const kSmsReadSuccessObserverTopic       = "sms-read-success";
 const kSmsReadErrorObserverTopic         = "sms-read-error";
+const kSmsDeletedObserverTopic           = "sms-deleted";
 
 const NS_XPCOM_SHUTDOWN_OBSERVER_ID      = "xpcom-shutdown";
 const kNetworkConnStateChangedTopic      = "network-connection-state-changed";
-const kMobileMessageDeletedObserverTopic = "mobile-message-deleted";
 
 const kPrefRilRadioDisabled              = "ril.radio.disabled";
 
 // HTTP status codes:
 // @see http://tools.ietf.org/html/rfc2616#page-39
 const HTTP_STATUS_OK = 200;
 
 // Non-standard HTTP status for internal use.
@@ -905,30 +905,30 @@ CancellableTransaction.prototype = {
 
   isObserversAdded: false,
 
   cancelledReason: _MMS_ERROR_USER_CANCELLED_NO_REASON,
 
   registerRunCallback: function(callback) {
     if (!this.isObserversAdded) {
       Services.obs.addObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false);
-      Services.obs.addObserver(this, kMobileMessageDeletedObserverTopic, false);
+      Services.obs.addObserver(this, kSmsDeletedObserverTopic, false);
       Services.prefs.addObserver(kPrefRilRadioDisabled, this, false);
       Services.prefs.addObserver(kPrefDefaultServiceId, this, false);
       this.isObserversAdded = true;
     }
 
     this.runCallback = callback;
     this.isCancelled = false;
   },
 
   removeObservers: function() {
     if (this.isObserversAdded) {
       Services.obs.removeObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID);
-      Services.obs.removeObserver(this, kMobileMessageDeletedObserverTopic);
+      Services.obs.removeObserver(this, kSmsDeletedObserverTopic);
       Services.prefs.removeObserver(kPrefRilRadioDisabled, this);
       Services.prefs.removeObserver(kPrefDefaultServiceId, this);
       this.isObserversAdded = false;
     }
   },
 
   runCallbackIfValid: function(mmsStatus, msg) {
     this.removeObservers();
@@ -967,23 +967,21 @@ CancellableTransaction.prototype = {
   // nsIObserver
 
   observe: function(subject, topic, data) {
     switch (topic) {
       case NS_XPCOM_SHUTDOWN_OBSERVER_ID: {
         this.cancelRunning(_MMS_ERROR_SHUTDOWN);
         break;
       }
-      case kMobileMessageDeletedObserverTopic: {
-        data = JSON.parse(data);
-        if (data.id != this.cancellableId) {
-          return;
+      case kSmsDeletedObserverTopic: {
+        if (subject && subject.deletedMessageIds &&
+            subject.deletedMessageIds.indexOf(this.cancellableId) >= 0) {
+          this.cancelRunning(_MMS_ERROR_MESSAGE_DELETED);
         }
-
-        this.cancelRunning(_MMS_ERROR_MESSAGE_DELETED);
         break;
       }
       case NS_PREFBRANCH_PREFCHANGE_TOPIC_ID: {
         if (data == kPrefRilRadioDisabled) {
           if (getRadioDisabledState()) {
             this.cancelRunning(_MMS_ERROR_RADIO_DISABLED);
           }
         } else if (data === kPrefDefaultServiceId &&
--- a/dom/mobilemessage/src/gonk/MobileMessageDB.jsm
+++ b/dom/mobilemessage/src/gonk/MobileMessageDB.jsm
@@ -2087,49 +2087,54 @@ MobileMessageDB.prototype = {
         aCallback.notify(aRv, domMessage);
       };
 
       if (error) {
         notifyResult(error, null);
         return;
       }
 
+      let deletedInfo = { messageIds: [], threadIds: [] };
+
       txn.oncomplete = function oncomplete(event) {
         if (aMessageRecord.id > self.lastMessageId) {
           self.lastMessageId = aMessageRecord.id;
         }
         notifyResult(Cr.NS_OK, aMessageRecord);
+        self.notifyDeletedInfo(deletedInfo);
       };
       txn.onabort = function onabort(event) {
         // TODO bug 832140 check event.target.errorCode
         notifyResult(Cr.NS_ERROR_FAILURE, null);
       };
 
       let messageStore = stores[0];
       let participantStore = stores[1];
       let threadStore = stores[2];
       self.replaceShortMessageOnSave(txn, messageStore, participantStore,
                                      threadStore, aMessageRecord,
-                                     aThreadParticipants);
+                                     aThreadParticipants, deletedInfo);
     }, [MESSAGE_STORE_NAME, PARTICIPANT_STORE_NAME, THREAD_STORE_NAME]);
   },
 
   replaceShortMessageOnSave: function(aTransaction, aMessageStore,
                                       aParticipantStore, aThreadStore,
-                                      aMessageRecord, aThreadParticipants) {
+                                      aMessageRecord, aThreadParticipants,
+                                      aDeletedInfo) {
     let isReplaceTypePid = (aMessageRecord.pid) &&
                            ((aMessageRecord.pid >= RIL.PDU_PID_REPLACE_SHORT_MESSAGE_TYPE_1 &&
                              aMessageRecord.pid <= RIL.PDU_PID_REPLACE_SHORT_MESSAGE_TYPE_7) ||
                             aMessageRecord.pid == RIL.PDU_PID_RETURN_CALL_MESSAGE);
 
     if (aMessageRecord.type != "sms" ||
         aMessageRecord.delivery != DELIVERY_RECEIVED ||
         !isReplaceTypePid) {
       this.realSaveRecord(aTransaction, aMessageStore, aParticipantStore,
-                          aThreadStore, aMessageRecord, aThreadParticipants);
+                          aThreadStore, aMessageRecord, aThreadParticipants,
+                          aDeletedInfo);
       return;
     }
 
     // 3GPP TS 23.040 subclause 9.2.3.9 "TP-Protocol-Identifier (TP-PID)":
     //
     //   ... the MS shall check the originating address and replace any
     //   existing stored message having the same Protocol Identifier code
     //   and originating address with the new short message and other
@@ -2141,51 +2146,55 @@ MobileMessageDB.prototype = {
       address: aMessageRecord.sender,
       type: MMS.Address.resolveType(aMessageRecord.sender)
     };
     this.findParticipantRecordByTypedAddress(aParticipantStore, typedSender,
                                              false,
                                              function(participantRecord) {
       if (!participantRecord) {
         self.realSaveRecord(aTransaction, aMessageStore, aParticipantStore,
-                            aThreadStore, aMessageRecord, aThreadParticipants);
+                            aThreadStore, aMessageRecord, aThreadParticipants,
+                            aDeletedInfo);
         return;
       }
 
       let participantId = participantRecord.id;
       let range = IDBKeyRange.bound([participantId, 0], [participantId, ""]);
       let request = aMessageStore.index("participantIds").openCursor(range);
       request.onsuccess = function onsuccess(event) {
         let cursor = event.target.result;
         if (!cursor) {
           self.realSaveRecord(aTransaction, aMessageStore, aParticipantStore,
-                              aThreadStore, aMessageRecord, aThreadParticipants);
+                              aThreadStore, aMessageRecord, aThreadParticipants,
+                              aDeletedInfo);
           return;
         }
 
         // A message record with same participantId found.
         // Verify matching criteria.
         let foundMessageRecord = cursor.value;
         if (foundMessageRecord.type != "sms" ||
             foundMessageRecord.sender != aMessageRecord.sender ||
             foundMessageRecord.pid != aMessageRecord.pid) {
           cursor.continue();
           return;
         }
 
         // Match! Now replace that found message record with current one.
         aMessageRecord.id = foundMessageRecord.id;
         self.realSaveRecord(aTransaction, aMessageStore, aParticipantStore,
-                            aThreadStore, aMessageRecord, aThreadParticipants);
+                            aThreadStore, aMessageRecord, aThreadParticipants,
+                            aDeletedInfo);
       };
     });
   },
 
   realSaveRecord: function(aTransaction, aMessageStore, aParticipantStore,
-                           aThreadStore, aMessageRecord, aThreadParticipants) {
+                           aThreadStore, aMessageRecord, aThreadParticipants,
+                           aDeletedInfo) {
     let self = this;
     this.findThreadRecordByTypedAddresses(aThreadStore, aParticipantStore,
                                           aThreadParticipants, true,
                                           function(threadRecord,
                                                    participantIds) {
       if (!participantIds) {
         aTransaction.abort();
         return;
@@ -2221,17 +2230,18 @@ MobileMessageDB.prototype = {
         aMessageStore.get(aMessageRecord.id).onsuccess = function(event) {
           let oldMessageRecord = event.target.result;
           aMessageStore.put(aMessageRecord);
           if (oldMessageRecord) {
             self.updateThreadByMessageChange(aMessageStore,
                                              aThreadStore,
                                              oldMessageRecord.threadId,
                                              aMessageRecord.id,
-                                             oldMessageRecord.read);
+                                             oldMessageRecord.read,
+                                             aDeletedInfo);
           }
         };
       };
 
       if (threadRecord) {
         let needsUpdate = false;
 
         if (threadRecord.lastTimestamp <= timestamp) {
@@ -2471,17 +2481,18 @@ MobileMessageDB.prototype = {
         return {
           address: aAddress,
           type: MMS.Address.resolveType(aAddress)
         };
       });
   },
 
   updateThreadByMessageChange: function(messageStore, threadStore, threadId,
-                                        messageId, messageRead) {
+                                        messageId, messageRead, deletedInfo) {
+    let self = this;
     threadStore.get(threadId).onsuccess = function(event) {
       // This must exist.
       let threadRecord = event.target.result;
       if (DEBUG) debug("Updating thread record " + JSON.stringify(threadRecord));
 
       if (!messageRead) {
         threadRecord.unreadCount--;
       }
@@ -2493,16 +2504,19 @@ MobileMessageDB.prototype = {
                                   .openCursor(range, PREV);
         request.onsuccess = function(event) {
           let cursor = event.target.result;
           if (!cursor) {
             if (DEBUG) {
               debug("Deleting mru entry for thread id " + threadId);
             }
             threadStore.delete(threadId);
+            if (deletedInfo) {
+              deletedInfo.threadIds.push(threadId);
+            }
             return;
           }
 
           let nextMsg = cursor.value;
           let lastMessageSubject;
           if (nextMsg.type == "mms") {
             lastMessageSubject = nextMsg.headers.subject;
           }
@@ -2524,16 +2538,30 @@ MobileMessageDB.prototype = {
                 (threadRecord.unreadCount + 1) + " -> " +
                 threadRecord.unreadCount);
         }
         threadStore.put(threadRecord);
       }
     };
   },
 
+  notifyDeletedInfo: function(info) {
+    if (!info) {
+      return;
+    }
+
+    let deletedInfo =
+      gMobileMessageService
+      .createDeletedMessageInfo(info.messageIds,
+                                info.messageIds.length,
+                                info.threadIds,
+                                info.threadIds.length);
+    Services.obs.notifyObservers(deletedInfo, "sms-deleted", null);
+  },
+
   /**
    * nsIRilMobileMessageDatabaseService API
    */
 
   saveReceivedMessage: function(aMessage, aCallback) {
     if ((aMessage.type != "sms" && aMessage.type != "mms") ||
         (aMessage.type == "sms" && (aMessage.messageClass == undefined ||
                                     aMessage.sender == undefined)) ||
@@ -2985,54 +3013,59 @@ MobileMessageDB.prototype = {
     let self = this;
     this.newTxn(READ_WRITE, function(error, txn, stores) {
       if (error) {
         if (DEBUG) debug("deleteMessage: failed to open transaction");
         aRequest.notifyDeleteMessageFailed(
           self.translateCrErrorToMessageCallbackError(error));
         return;
       }
+
+      let deletedInfo = { messageIds: [], threadIds: [] };
+
       txn.onerror = function onerror(event) {
         if (DEBUG) debug("Caught error on transaction", event.target.errorCode);
         //TODO look at event.target.errorCode, pick appropriate error constant
         aRequest.notifyDeleteMessageFailed(Ci.nsIMobileMessageCallback.INTERNAL_ERROR);
       };
 
       const messageStore = stores[0];
       const threadStore = stores[1];
 
       txn.oncomplete = function oncomplete(event) {
         if (DEBUG) debug("Transaction " + txn + " completed.");
         aRequest.notifyMessageDeleted(deleted, length);
+        self.notifyDeletedInfo(deletedInfo);
       };
 
       for (let i = 0; i < length; i++) {
         let messageId = messageIds[i];
         deleted[i] = false;
         messageStore.get(messageId).onsuccess = function(messageIndex, event) {
           let messageRecord = event.target.result;
           let messageId = messageIds[messageIndex];
           if (messageRecord) {
             if (DEBUG) debug("Deleting message id " + messageId);
 
             // First actually delete the message.
             messageStore.delete(messageId).onsuccess = function(event) {
               if (DEBUG) debug("Message id " + messageId + " deleted");
+              if (deletedInfo) {
+                deletedInfo.messageIds.push(messageId);
+              }
+
               deleted[messageIndex] = true;
 
               // Then update unread count and most recent message.
               self.updateThreadByMessageChange(messageStore,
                                                threadStore,
                                                messageRecord.threadId,
                                                messageId,
-                                               messageRecord.read);
-
-              Services.obs.notifyObservers(null,
-                                           "mobile-message-deleted",
-                                           JSON.stringify({ id: messageId }));
+                                               messageRecord.read,
+                                               deletedInfo);
             };
           } else if (DEBUG) {
             debug("Message id " + messageId + " does not exist");
           }
         }.bind(null, i);
       }
     }, [MESSAGE_STORE_NAME, THREAD_STORE_NAME]);
   },