Bug 1555294 - Adding addrbook-list-member-removed observer notification (test by darktrojan). r=mkmelin
authorJohn Bieling <john.bieling@gmx.de>
Thu, 06 Jun 2019 18:27:02 +0200
changeset 35793 0f025fb08630db2c60540b8a82fb0fbc9cc17964
parent 35792 20fc951885d9772e559459f83261e25f48bd77a0
child 35794 b492a5b976afeb2461bd0a8bffb9ab835d679dab
push id392
push userclokep@gmail.com
push dateMon, 02 Sep 2019 20:17:19 +0000
reviewersmkmelin
bugs1555294
Bug 1555294 - Adding addrbook-list-member-removed observer notification (test by darktrojan). r=mkmelin
mailnews/addrbook/src/nsAddrDatabase.cpp
mailnews/addrbook/src/nsAddrDatabase.h
mailnews/addrbook/test/unit/test_notifications.js
--- a/mailnews/addrbook/src/nsAddrDatabase.cpp
+++ b/mailnews/addrbook/src/nsAddrDatabase.cpp
@@ -1431,35 +1431,54 @@ NS_IMETHODIMP nsAddrDatabase::CreateMail
 
     NS_RELEASE(listRow);
     return NS_OK;
   }
 
   return NS_ERROR_FAILURE;
 }
 
-void nsAddrDatabase::DeleteCardFromAllMailLists(mdb_id cardRowID) {
+void nsAddrDatabase::DeleteCardFromAllMailLists(nsIAbCard *aCard) {
   if (!m_mdbEnv) return;
 
+  mdb_id cardRowID;
+  nsresult rv = aCard->GetPropertyAsUint32(kRowIDProperty, &cardRowID);
+  if (NS_FAILED(rv)) {
+    return;
+  }
+
   nsCOMPtr<nsIMdbTableRowCursor> rowCursor;
   m_mdbPabTable->GetTableRowCursor(m_mdbEnv, -1, getter_AddRefs(rowCursor));
 
   if (rowCursor) {
     nsCOMPtr<nsIMdbRow> pListRow;
     mdb_pos rowPos;
     do {
-      nsresult err =
-          rowCursor->NextRow(m_mdbEnv, getter_AddRefs(pListRow), &rowPos);
-
-      if (NS_SUCCEEDED(err) && pListRow) {
+      rv = rowCursor->NextRow(m_mdbEnv, getter_AddRefs(pListRow), &rowPos);
+
+      if (NS_SUCCEEDED(rv) && pListRow) {
         mdbOid rowOid;
 
         if (NS_SUCCEEDED(pListRow->GetOid(m_mdbEnv, &rowOid))) {
-          if (IsListRowScopeToken(rowOid.mOid_Scope))
-            DeleteCardFromListRow(pListRow, cardRowID);
+          if (IsListRowScopeToken(rowOid.mOid_Scope)) {
+            bool cardFound = false;
+            DeleteCardFromListRow(pListRow, cardRowID, &cardFound);
+            if (cardFound) {
+              nsCOMPtr<nsIObserverService> observerService =
+                  mozilla::services::GetObserverService();
+              if (observerService) {
+                nsAutoString listUID;
+                GetStringColumn(pListRow, m_UIDColumnToken, listUID);
+                if (!listUID.IsEmpty()) {
+                  observerService->NotifyObservers(
+                      aCard, "addrbook-list-member-removed", listUID.get());
+                }
+              }
+            }
+          }
         }
       }
     } while (pListRow);
   }
 }
 
 NS_IMETHODIMP nsAddrDatabase::DeleteCard(nsIAbCard *aCard, bool aNotify,
                                          nsIAbDirectory *aParent) {
@@ -1478,16 +1497,19 @@ NS_IMETHODIMP nsAddrDatabase::DeleteCard
 
   err = aCard->GetPropertyAsUint32(kRowIDProperty, &rowOid.mOid_Id);
   NS_ENSURE_SUCCESS(err, err);
 
   err = m_mdbStore->GetRow(m_mdbEnv, &rowOid, &pCardRow);
   NS_ENSURE_SUCCESS(err, err);
   if (!pCardRow) return NS_OK;
 
+  // Delete the person card from all mailing list.
+  if (!bIsMailList) DeleteCardFromAllMailLists(aCard);
+
   // Reset the directory id
   aCard->SetDirectoryId(EmptyCString());
 
   // And here a greeting from the quirky old past:
   // Before there was a "deleted cards" table where deleted cards
   // were stored for six month. If we find this table, we empty it out.
   if (!m_mdbDeletedCardsTableRemoved) {
     m_mdbDeletedCardsTableRemoved = true;
@@ -1500,29 +1522,27 @@ NS_IMETHODIMP nsAddrDatabase::DeleteCard
       deletedCardsTable->CutAllRows(m_mdbEnv);
       deletedCardsTable->Release();
       Commit(nsAddrDBCommitType::kCompressCommit);
     }
   }
 
   err = DeleteRow(m_mdbPabTable, pCardRow);
 
-  // delete the person card from all mailing list
-  if (!bIsMailList) DeleteCardFromAllMailLists(rowOid.mOid_Id);
-
   if (NS_SUCCEEDED(err)) {
     if (aNotify) NotifyCardEntryChange(AB_NotifyDeleted, aCard, aParent);
   }
 
   NS_RELEASE(pCardRow);
   return NS_OK;
 }
 
 nsresult nsAddrDatabase::DeleteCardFromListRow(nsIMdbRow *pListRow,
-                                               mdb_id cardRowID) {
+                                               mdb_id cardRowID,
+                                               bool *cardFound) {
   NS_ENSURE_ARG_POINTER(pListRow);
   if (!m_mdbStore || !m_mdbEnv) return NS_ERROR_NULL_POINTER;
 
   nsresult err = NS_OK;
 
   uint32_t totalAddress = GetListAddressTotal(pListRow);
 
   uint32_t pos;
@@ -1532,16 +1552,17 @@ nsresult nsAddrDatabase::DeleteCardFromL
 
     char columnStr[COLUMN_STR_MAX];
     PR_snprintf(columnStr, COLUMN_STR_MAX, kMailListAddressFormat, pos);
     m_mdbStore->StringToToken(m_mdbEnv, columnStr, &listAddressColumnToken);
 
     err = GetIntColumn(pListRow, listAddressColumnToken, (uint32_t *)&rowID, 0);
 
     if (cardRowID == rowID) {
+      *cardFound = true;
       if (pos == totalAddress)
         err = pListRow->CutColumn(m_mdbEnv, listAddressColumnToken);
       else {
         // replace the deleted one with the last one and delete the last one
         mdb_id lastRowID;
         mdb_token lastAddressColumnToken;
         PR_snprintf(columnStr, COLUMN_STR_MAX, kMailListAddressFormat,
                     totalAddress);
@@ -1589,19 +1610,32 @@ NS_IMETHODIMP nsAddrDatabase::DeleteCard
   NS_ENSURE_SUCCESS(err, err);
   if (!pListRow) return NS_OK;
 
   uint32_t cardRowID;
 
   err = card->GetPropertyAsUint32(kRowIDProperty, &cardRowID);
   if (NS_FAILED(err)) return NS_ERROR_NULL_POINTER;
 
-  err = DeleteCardFromListRow(pListRow, cardRowID);
+  bool cardFound = false;
+  err = DeleteCardFromListRow(pListRow, cardRowID, &cardFound);
   if (NS_SUCCEEDED(err) && aNotify) {
     NotifyCardEntryChange(AB_NotifyDeleted, card, mailList);
+    // Notify the addrbook-list-member-removed observer if the card was found
+    // and removed.
+    if (cardFound) {
+      nsCOMPtr<nsIObserverService> observerService =
+          mozilla::services::GetObserverService();
+      if (observerService) {
+        nsAutoCString listUID;
+        mailList->GetUID(listUID);
+        observerService->NotifyObservers(card, "addrbook-list-member-removed",
+                                         NS_ConvertUTF8toUTF16(listUID).get());
+      }
+    }
   }
   NS_RELEASE(pListRow);
   return NS_OK;
 }
 
 NS_IMETHODIMP nsAddrDatabase::SetCardValue(nsIAbCard *card, const char *name,
                                            const char16_t *value, bool notify) {
   NS_ENSURE_ARG_POINTER(card);
--- a/mailnews/addrbook/src/nsAddrDatabase.h
+++ b/mailnews/addrbook/src/nsAddrDatabase.h
@@ -383,18 +383,19 @@ class nsAddrDatabase : public nsIAddrDat
   nsresult AddRecordKeyColumnToRow(nsIMdbRow *pRow);
   nsresult AddAttributeColumnsToRow(nsIAbCard *card, nsIMdbRow *cardRow);
   nsresult AddListAttributeColumnsToRow(nsIAbDirectory *list,
                                         nsIMdbRow *listRow,
                                         nsIAbDirectory *parent);
   nsresult CreateCard(nsIMdbRow *cardRow, mdb_id listRowID, nsIAbCard **result);
   nsresult CreateCardFromDeletedCardsTable(nsIMdbRow *cardRow, mdb_id listRowID,
                                            nsIAbCard **result);
-  nsresult DeleteCardFromListRow(nsIMdbRow *pListRow, mdb_id cardRowID);
-  void DeleteCardFromAllMailLists(mdb_id cardRowID);
+  nsresult DeleteCardFromListRow(nsIMdbRow *pListRow, mdb_id cardRowID,
+                                 bool *cardFound);
+  void DeleteCardFromAllMailLists(nsIAbCard *aCard);
   nsresult NotifyListEntryChange(uint32_t abCode, nsIAbDirectory *dir);
 
   nsresult AddLowercaseColumn(nsIMdbRow *row, mdb_token columnToken,
                               const char *utf8String);
   nsresult GetRowFromAttribute(const char *aName, const nsACString &aUTF8Value,
                                bool aCaseInsensitive, nsIMdbRow **aCardRow,
                                mdb_pos *aRowPos);
 
--- a/mailnews/addrbook/test/unit/test_notifications.js
+++ b/mailnews/addrbook/test/unit/test_notifications.js
@@ -20,21 +20,34 @@ var abListener = {
     this.result.push(["onItemRemoved", parentItem, item]);
   },
   onItemPropertyChanged(item, property, oldValue, newValue) {
     Assert.ok(this.result.length < this.maxResults);
     this.result.push(["onItemPropertyChanged", item, property, oldValue, newValue]);
   },
 };
 
+var abObserver = {
+  result: [],
+  maxResults: 1,
+  observe(subject, topic, data) {
+    Assert.ok(this.result.length < this.maxResults);
+    this.result.push([subject, topic, data]);
+  },
+};
+
 function run_test() {
   // XXX Getting all directories ensures we create all ABs because the
   // address collecter can't currently create ABs itself (bug 314448).
   MailServices.ab.directories;
 
+  run_next_test();
+}
+
+add_test(function() {
   // Add a listener
   MailServices.ab.addAddressBookListener(abListener, Ci.nsIAbListener.all);
 
   // Get the directory
   let AB = MailServices.ab.getDirectory(kPABData.URI);
 
   // For card tests, the most we expect is one notification.
   abListener.maxResults = 1;
@@ -142,9 +155,64 @@ function run_test() {
   Assert.ok(book.isMailList);
   Assert.equal(book.dirName, "TestList");
   Assert.equal(book.listNickName, "test");
   Assert.equal(book.description, "testdescription");
 
   // Remove listener
 
   MailServices.ab.removeAddressBookListener(abListener);
-}
+
+  run_next_test();
+});
+
+add_test(function() {
+  let dirName = MailServices.ab.newAddressBook("TestBook", "", kPABData.dirType);
+  let AB = MailServices.ab.getDirectoryFromId(dirName);
+
+  let mailList = Cc["@mozilla.org/addressbook/directoryproperty;1"]
+                   .createInstance(Ci.nsIAbDirectory);
+  mailList.isMailList = true;
+  mailList.dirName = "TestList";
+  mailList = AB.addMailList(mailList);
+
+  let card1 = Cc["@mozilla.org/addressbook/cardproperty;1"]
+                .createInstance(Ci.nsIAbCard);
+  card1.firstName = "test1";
+  card1.primaryEmail = "test1@foo.invalid";
+  card1 = AB.addCard(card1);
+
+  let card2 = Cc["@mozilla.org/addressbook/cardproperty;1"]
+                .createInstance(Ci.nsIAbCard);
+  card2.firstName = "test2";
+  card2.primaryEmail = "test2@foo.invalid";
+  card2 = AB.addCard(card2);
+  mailList.addCard(card2);
+
+  // Test: remove one card that ISN'T in the mailing list
+
+  Services.obs.addObserver(abObserver, "addrbook-list-member-removed");
+  abObserver.maxResults = 0;
+  abObserver.result = [];
+
+  let cardsToDelete = Cc["@mozilla.org/array;1"]
+                        .createInstance(Ci.nsIMutableArray);
+  cardsToDelete.appendElement(card1);
+  AB.deleteCards(cardsToDelete);
+
+  // Test: remove one card that IS in the mailing list
+
+  abObserver.maxResults = 1;
+  abObserver.result = [];
+
+  cardsToDelete.clear();
+  cardsToDelete.appendElement(card2);
+  AB.deleteCards(cardsToDelete);
+
+  Assert.equal(abObserver.result.length, 1);
+  Assert.equal(abObserver.result[0][0], card2);
+  Assert.equal(abObserver.result[0][1], "addrbook-list-member-removed");
+  Assert.equal(abObserver.result[0][2], mailList.UID);
+
+  Services.obs.removeObserver(abObserver, "addrbook-list-member-removed");
+
+  run_next_test();
+});