Bug 1633607 - Fire observer service notifications as well as nsIAbListener events. r=mkmelin
authorGeoff Lankow <geoff@darktrojan.net>
Fri, 24 Apr 2020 21:09:41 +1200
changeset 38957 69e91e0bc92ce7e94f97a3069e2949bbca3c840f
parent 38956 370823b8dff7d6ea7eb19587aa92c709443df5c1
child 38958 9eda2be91b4ed91bf64cb4571e1d70c360146225
push id401
push userclokep@gmail.com
push dateMon, 01 Jun 2020 20:41:59 +0000
reviewersmkmelin
bugs1633607
Bug 1633607 - Fire observer service notifications as well as nsIAbListener events. r=mkmelin
mail/components/extensions/parent/ext-addressBook.js
mailnews/addrbook/jsaddrbook/AddrBookDirectory.jsm
mailnews/addrbook/jsaddrbook/AddrBookMailingList.jsm
mailnews/addrbook/jsaddrbook/AddrBookManager.jsm
mailnews/addrbook/test/unit/test_jsaddrbook.js
--- a/mail/components/extensions/parent/ext-addressBook.js
+++ b/mail/components/extensions/parent/ext-addressBook.js
@@ -247,28 +247,16 @@ var addressBookCache = new (class extend
         this.emit("mailing-list-created", newNode);
       } else if (!item.readOnly) {
         let newNode = this._makeDirectoryNode(item);
         if (this._addressBooks) {
           this._addressBooks.set(newNode.id, newNode);
         }
         this.emit("address-book-created", newNode);
       }
-    } else if (item instanceof Ci.nsIAbCard) {
-      item.QueryInterface(Ci.nsIAbCard);
-      if (!item.isMailList && parent.isMailList) {
-        let newNode = this._makeContactNode(item, parent);
-        if (
-          this._mailingLists.has(parent.UID) &&
-          this._mailingLists.get(parent.UID).contacts
-        ) {
-          this._mailingLists.get(parent.UID).contacts.set(newNode.id, newNode);
-        }
-        this.emit("mailing-list-member-added", newNode);
-      }
     }
   }
   // nsIAbListener
   onItemRemoved(parent, item) {
     if (parent) {
       parent = parent.QueryInterface(Ci.nsIAbDirectory);
     } // Otherwise item is a removed address book and we don't use parent.
 
--- a/mailnews/addrbook/jsaddrbook/AddrBookDirectory.jsm
+++ b/mailnews/addrbook/jsaddrbook/AddrBookDirectory.jsm
@@ -524,16 +524,17 @@ AddrBookDirectoryInner.prototype = {
   },
   get dirName() {
     return this.getLocalizedStringValue("description", "");
   },
   set dirName(value) {
     let oldValue = this.dirName;
     this.setLocalizedStringValue("description", value);
     MailServices.ab.notifyItemPropertyChanged(this, "DirName", oldValue, value);
+    Services.obs.notifyObservers(this, "addrbook-directory-updated", "DirName");
   },
   get dirType() {
     return 101;
   },
   get fileName() {
     return this._fileName;
   },
   get UID() {
@@ -755,16 +756,21 @@ AddrBookDirectoryInner.prototype = {
     }
 
     this._dbConnection.executeSimpleSQL(
       "DELETE FROM list_cards WHERE list NOT IN (SELECT DISTINCT uid FROM lists)"
     );
     MailServices.ab.notifyDirectoryItemDeleted(this, list.asCard);
     MailServices.ab.notifyDirectoryItemDeleted(list.asDirectory, list.asCard);
     MailServices.ab.notifyDirectoryDeleted(this, directory);
+    Services.obs.notifyObservers(
+      list.asDirectory,
+      "addrbook-list-deleted",
+      this.UID
+    );
   },
   hasCard(card) {
     return this._lists.has(card.UID) || this._cards.has(card.UID);
   },
   hasDirectory(dir) {
     return this._lists.has(dir.UID);
   },
   hasMailListWithName(name) {
@@ -823,16 +829,17 @@ AddrBookDirectoryInner.prototype = {
         this._inner._cards.delete(card.UID);
       }
     }
     this._dbConnection.executeSimpleSQL(
       "DELETE FROM properties WHERE card NOT IN (SELECT DISTINCT uid FROM cards)"
     );
     for (let card of cards.enumerate(Ci.nsIAbCard)) {
       MailServices.ab.notifyDirectoryItemDeleted(this, card);
+      Services.obs.notifyObservers(card, "addrbook-contact-deleted", this.UID);
     }
 
     // We could just delete all non-existent cards from list_cards, but a
     // notification should be fired for each one. Let the list handle that.
     for (let list of this.childNodes) {
       list.deleteCards(cards);
     }
 
@@ -906,16 +913,21 @@ AddrBookDirectoryInner.prototype = {
       list.listNickName || "",
       list.description || ""
     );
     this._saveList(newList);
 
     let newListDirectory = newList.asDirectory;
     MailServices.ab.notifyDirectoryItemAdded(this, newList.asCard);
     MailServices.ab.notifyDirectoryItemAdded(this, newListDirectory);
+    Services.obs.notifyObservers(
+      newList.asDirectory,
+      "addrbook-list-created",
+      this.UID
+    );
     return newListDirectory;
   },
   editMailListToDatabase(listCard) {
     // Deliberately not implemented, this isn't a mailing list.
     throw Cr.NS_ERROR_NOT_IMPLEMENTED;
   },
   copyMailList(srcList) {
     throw Cr.NS_ERROR_NOT_IMPLEMENTED;
--- a/mailnews/addrbook/jsaddrbook/AddrBookMailingList.jsm
+++ b/mailnews/addrbook/jsaddrbook/AddrBookMailingList.jsm
@@ -132,17 +132,21 @@ AddrBookMailingList.prototype = {
         );
         insertStatement.params.list = self._uid;
         insertStatement.params.card = card.UID;
         insertStatement.execute();
         MailServices.ab.notifyItemPropertyChanged(card, null, null, null);
         MailServices.ab.notifyItemPropertyChanged(card, null, null, null);
         MailServices.ab.notifyDirectoryItemAdded(self._parent, card);
         MailServices.ab.notifyDirectoryItemAdded(this, card);
-        // Services.obs.notifyObservers(card, "addrbook-list-member-added", self._uid);
+        Services.obs.notifyObservers(
+          card,
+          "addrbook-list-member-added",
+          self._uid
+        );
         insertStatement.finalize();
         return card;
       },
       deleteCards(cards) {
         let deleteCardStatement = self._parent._dbConnection.createStatement(
           "DELETE FROM list_cards WHERE list = :list AND card = :card"
         );
         for (let card of fixIterator(cards, Ci.nsIAbCard)) {
--- a/mailnews/addrbook/jsaddrbook/AddrBookManager.jsm
+++ b/mailnews/addrbook/jsaddrbook/AddrBookManager.jsm
@@ -252,16 +252,17 @@ AddrBookManager.prototype = {
         ensureUniquePrefName();
         Services.prefs.setStringPref(`${prefName}.description`, dirName);
         Services.prefs.setStringPref(`${prefName}.filename`, file.leafName);
         Services.prefs.setStringPref(`${prefName}.uri`, uri);
 
         uri = `moz-abldapdirectory://${prefName}`;
         let dir = createDirectoryObject(uri, true);
         this.notifyDirectoryItemAdded(null, dir);
+        Services.obs.notifyObservers(dir, "addrbook-directory-created");
         break;
       }
       case MAPI_DIRECTORY_TYPE: {
         if (AppConstants.platform == "macosx") {
           uri = "moz-abosxdirectory:///";
           if (store.has(uri)) {
             throw Cr.NS_ERROR_UNEXPECTED;
           }
@@ -288,23 +289,25 @@ AddrBookManager.prototype = {
           `${prefName}.description`,
           "chrome://messenger/locale/addressbook/addressBook.properties"
         );
         Services.prefs.setStringPref(`${prefName}.uri`, uri);
 
         if (AppConstants.platform == "macosx") {
           let dir = createDirectoryObject(uri, true);
           this.notifyDirectoryItemAdded(null, dir);
+          Services.obs.notifyObservers(dir, "addrbook-directory-created");
         } else if (AppConstants.platform == "win") {
           let outlookInterface = Cc[
             "@mozilla.org/addressbook/outlookinterface;1"
           ].getService(Ci.nsIAbOutlookInterface);
           for (let folderURI of outlookInterface.getFolderURIs(uri)) {
             let dir = createDirectoryObject(folderURI, true);
             this.notifyDirectoryItemAdded(null, dir);
+            Services.obs.notifyObservers(dir, "addrbook-directory-created");
           }
         }
         break;
       }
       case JS_DIRECTORY_TYPE: {
         let file = Services.dirsvc.get("ProfD", Ci.nsIFile);
         file.append("abook.sqlite");
         file.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0o644);
@@ -312,16 +315,17 @@ AddrBookManager.prototype = {
         ensureUniquePrefName();
         Services.prefs.setStringPref(`${prefName}.description`, dirName);
         Services.prefs.setIntPref(`${prefName}.dirType`, type);
         Services.prefs.setStringPref(`${prefName}.filename`, file.leafName);
 
         uri = `jsaddrbook://${file.leafName}`;
         let dir = createDirectoryObject(uri, true);
         this.notifyDirectoryItemAdded(null, dir);
+        Services.obs.notifyObservers(dir, "addrbook-directory-created");
         break;
       }
       default:
         throw Cr.NS_ERROR_UNEXPECTED;
     }
 
     return prefName;
   },
@@ -385,19 +389,21 @@ AddrBookManager.prototype = {
     if (fileName) {
       let file = Services.dirsvc.get("ProfD", Ci.nsIFile);
       file.append(fileName);
       closeConnectionTo(file).then(() => {
         if (file.exists()) {
           file.remove(false);
         }
         this.notifyDirectoryDeleted(null, dir);
+        Services.obs.notifyObservers(dir, "addrbook-directory-deleted");
       });
     } else {
       this.notifyDirectoryDeleted(null, dir);
+      Services.obs.notifyObservers(dir, "addrbook-directory-deleted");
     }
   },
   addAddressBookListener(listener, notifyFlags) {
     listeners.set(listener, notifyFlags);
   },
   removeAddressBookListener(listener) {
     listeners.delete(listener);
   },
--- a/mailnews/addrbook/test/unit/test_jsaddrbook.js
+++ b/mailnews/addrbook/test/unit/test_jsaddrbook.js
@@ -10,29 +10,40 @@ var SCHEME = "jsaddrbook";
 
 var { MailServices } = ChromeUtils.import(
   "resource:///modules/MailServices.jsm"
 );
 var { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
 
 var book, contact, list, listCard;
 var observer = {
+  topics: [
+    "addrbook-directory-created",
+    "addrbook-directory-updated",
+    "addrbook-directory-deleted",
+    "addrbook-contact-created",
+    "addrbook-contact-updated",
+    "addrbook-contact-deleted",
+    "addrbook-list-created",
+    "addrbook-list-updated",
+    "addrbook-list-deleted",
+    "addrbook-list-member-added",
+    "addrbook-list-member-removed",
+  ],
   setUp() {
     MailServices.ab.addAddressBookListener(observer, Ci.nsIAbListener.all);
-    Services.obs.addObserver(observer, "addrbook-contact-created");
-    Services.obs.addObserver(observer, "addrbook-contact-updated");
-    Services.obs.addObserver(observer, "addrbook-list-updated");
-    Services.obs.addObserver(observer, "addrbook-list-member-added");
+    for (let topic of this.topics) {
+      Services.obs.addObserver(observer, topic);
+    }
   },
   cleanUp() {
     MailServices.ab.removeAddressBookListener(observer);
-    Services.obs.removeObserver(observer, "addrbook-contact-created");
-    Services.obs.removeObserver(observer, "addrbook-contact-updated");
-    Services.obs.removeObserver(observer, "addrbook-list-updated");
-    Services.obs.removeObserver(observer, "addrbook-list-member-added");
+    for (let topic of this.topics) {
+      Services.obs.removeObserver(observer, topic);
+    }
   },
   promiseEvent() {
     return new Promise(resolve => {
       this.eventPromise = resolve;
     });
   },
   resolveEventPromise() {
     if (this.eventPromise) {
@@ -122,17 +133,20 @@ add_task(async function setUp() {
   let cabFile = profileDir.clone();
   cabFile.append(kCABData.fileName);
   ok(cabFile.exists());
 });
 
 add_task(async function createAddressBook() {
   let dirPrefId = MailServices.ab.newAddressBook("new book", "", DIR_TYPE);
   book = MailServices.ab.getDirectoryFromId(dirPrefId);
-  observer.checkEvents(["onItemAdded", undefined, book]);
+  observer.checkEvents(
+    ["onItemAdded", undefined, book],
+    ["addrbook-directory-created", book]
+  );
 
   // Check nsIAbDirectory properties.
   equal(book.uuid, "ldap_2.servers.newbook&new book");
   ok(!book.readOnly);
   ok(!book.isRemote);
   ok(!book.isSecure);
   equal(book.dirName, "new book");
   equal(book.dirType, DIR_TYPE);
@@ -164,23 +178,20 @@ add_task(async function createAddressBoo
   // Check the file was created.
   let dbFile = Services.dirsvc.get("ProfD", Ci.nsIFile);
   dbFile.append(FILE_NAME);
   ok(dbFile.exists());
 });
 
 add_task(async function editAddressBook() {
   book.dirName = "updated book";
-  observer.checkEvents([
-    "onItemPropertyChanged",
-    book,
-    "DirName",
-    "new book",
-    "updated book",
-  ]);
+  observer.checkEvents(
+    ["onItemPropertyChanged", book, "DirName", "new book", "updated book"],
+    ["addrbook-directory-updated", book, "DirName"]
+  );
   equal(book.dirName, "updated book");
   equal(
     Services.prefs.getStringPref("ldap_2.servers.newbook.description"),
     "updated book"
   );
 });
 
 add_task(async function createContact() {
@@ -267,17 +278,18 @@ add_task(async function createMailingLis
   } else {
     ok(childCards[0].equals(contact));
     listCard = childCards[1];
   }
   equal(listCard.UID, list.UID);
 
   observer.checkEvents(
     ["onItemAdded", book, listCard],
-    ["onItemAdded", book, list]
+    ["onItemAdded", book, list],
+    ["addrbook-list-created", list, book.UID]
   );
 
   // Check nsIAbDirectory properties.
   equal(list.uuid, "&new list");
   equal(list.dirName, "new list");
   equal(list.UID.length, 36);
   equal(list.URI, `${SCHEME}://${FILE_NAME}/MailList1`);
   equal(list.isMailList, true);
@@ -307,54 +319,61 @@ add_task(async function editMailingList(
 });
 
 add_task(async function addMailingListMember() {
   list.addCard(contact);
   observer.checkEvents(
     ["onItemPropertyChanged", contact, null, null, null],
     ["onItemPropertyChanged", contact, null, null, null],
     ["onItemAdded", book, contact],
-    ["onItemAdded", list, contact]
-    // ["addrbook-list-member-added", contact, list.UID] // MDB fires this on dropcard but not addcard?!
+    ["onItemAdded", list, contact],
+    ["addrbook-list-member-added", contact, list.UID]
   );
 
   // Check list enumerations.
   equal(Array.from(list.childNodes).length, 0);
   let childCards = Array.from(list.childCards, cc =>
     cc.QueryInterface(Ci.nsIAbCard)
   );
   equal(childCards.length, 1);
   ok(childCards[0].equals(contact));
 });
 
 add_task(async function removeMailingListMember() {
   let cardArray = Cc["@mozilla.org/array;1"].createInstance(Ci.nsIMutableArray);
   cardArray.appendElement(contact);
   list.deleteCards(cardArray);
-  observer.checkEvents(["onItemRemoved", list, contact]);
+  observer.checkEvents(
+    ["onItemRemoved", list, contact],
+    ["addrbook-list-member-removed", contact, list.UID]
+  );
 
   // Check list enumerations.
   equal(Array.from(list.childNodes).length, 0);
   equal(Array.from(list.childCards).length, 0);
 });
 
 add_task(async function deleteMailingList() {
   book.deleteDirectory(list);
   observer.checkEvents(
     ["onItemRemoved", book, listCard],
     ["onItemRemoved", list, listCard],
-    ["onItemRemoved", book, list]
+    ["onItemRemoved", book, list],
+    ["addrbook-list-deleted", list, book.UID]
   );
 });
 
 add_task(async function deleteContact() {
   let cardArray = Cc["@mozilla.org/array;1"].createInstance(Ci.nsIMutableArray);
   cardArray.appendElement(contact);
   book.deleteCards(cardArray);
-  observer.checkEvents(["onItemRemoved", book, contact]);
+  observer.checkEvents(
+    ["onItemRemoved", book, contact],
+    ["addrbook-contact-deleted", contact, book.UID]
+  );
 
   // Check enumerations.
   equal(Array.from(book.childNodes).length, 0);
   equal(Array.from(book.childCards).length, 0);
 });
 
 // Tests that the UID on a new contact can be set.
 add_task(async function createContactWithUID() {
@@ -379,17 +398,20 @@ add_task(async function createContactWit
   observer.events.length = 0;
 });
 
 add_task(async function deleteAddressBook() {
   let deletePromise = observer.promiseEvent();
   MailServices.ab.deleteAddressBook(book.URI);
   await deletePromise;
 
-  observer.checkEvents(["onItemRemoved", undefined, book]);
+  observer.checkEvents(
+    ["onItemRemoved", undefined, book],
+    ["addrbook-directory-deleted", book, null]
+  );
   ok(!Services.prefs.prefHasUserValue("ldap_2.servers.newbook.dirType"));
   ok(!Services.prefs.prefHasUserValue("ldap_2.servers.newbook.description"));
   ok(!Services.prefs.prefHasUserValue("ldap_2.servers.newbook.filename"));
   ok(!Services.prefs.prefHasUserValue("ldap_2.servers.newbook.uid"));
   let dbFile = Services.dirsvc.get("ProfD", Ci.nsIFile);
   dbFile.append(FILE_NAME);
   ok(!dbFile.exists());
   equal([...MailServices.ab.directories].length, 2);