Bug 1520737 - Ensure UID property is persistent for mailing list cards; r=mkmelin
--- a/mailnews/addrbook/src/nsAbDirProperty.cpp
+++ b/mailnews/addrbook/src/nsAbDirProperty.cpp
@@ -277,16 +277,20 @@ NS_IMETHODIMP nsAbDirProperty::CopyMailL
nsString str;
srcList->GetDirName(str);
SetDirName(str);
srcList->GetListNickName(str);
SetListNickName(str);
srcList->GetDescription(str);
SetDescription(str);
+ nsAutoCString uid;
+ srcList->GetUID(uid);
+ SetUID(uid);
+
nsCOMPtr<nsIMutableArray> pAddressLists;
srcList->GetAddressLists(getter_AddRefs(pAddressLists));
SetAddressLists(pAddressLists);
return NS_OK;
}
NS_IMETHODIMP nsAbDirProperty::GetIsQuery(bool *aResult)
{
--- a/mailnews/addrbook/src/nsAbMDBDirectory.cpp
+++ b/mailnews/addrbook/src/nsAbMDBDirectory.cpp
@@ -692,16 +692,41 @@ NS_IMETHODIMP nsAbMDBDirectory::ModifyCa
{
rv = GetAbDatabase();
NS_ENSURE_SUCCESS(rv, rv);
}
rv = mDatabase->EditCard(aModifiedCard, true, this);
NS_ENSURE_SUCCESS(rv, rv);
+ // If it's a mailing list's card, ensure the related nsIAbDirectory has the same UID.
+ bool isMailList;
+ rv = aModifiedCard->GetIsMailList(&isMailList);
+ NS_ENSURE_SUCCESS(rv, rv);
+ if (isMailList)
+ {
+ nsCOMPtr<nsIAbManager> abManager = do_GetService(NS_ABMANAGER_CONTRACTID, &rv);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsAutoCString uri;
+ rv = aModifiedCard->GetMailListURI(getter_Copies(uri));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsCOMPtr<nsIAbDirectory> directory;
+ rv = abManager->GetDirectory(uri, getter_AddRefs(directory));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsAutoCString uid;
+ rv = aModifiedCard->GetUID(uid);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ rv = directory->SetUID(uid);
+ NS_ENSURE_SUCCESS(rv, rv);
+ }
+
nsCOMPtr<nsIObserverService> observerService = mozilla::services::GetObserverService();
if (observerService) {
nsAutoCString thisUID;
this->GetUID(thisUID);
observerService->NotifyObservers(aModifiedCard, "addrbook-contact-updated", NS_ConvertUTF8toUTF16(thisUID).get());
}
return mDatabase->Commit(nsAddrDBCommitType::kLargeCommit);
--- a/mailnews/addrbook/test/unit/test_uid.js
+++ b/mailnews/addrbook/test/unit/test_uid.js
@@ -1,91 +1,121 @@
/*
* Test to check that pre-existing cards are given a UID,
* and that the UID remains the same after a shutdown.
*/
Cu.importGlobalProperties(["fetch"]);
var profD = do_get_profile();
-// Installs an address book with some existing objects.
-function run_test() {
- let testAB = do_get_file("data/existing.mab");
- testAB.copyTo(profD, kPABData.fileName);
-
- run_next_test();
-}
-
// Tests that directories have UIDs.
add_test(function directoryUID() {
+ newAddressBookFile();
+
for (let book of MailServices.ab.directories) {
equal(36, book.UID.length, "Existing directory has a UID");
}
let dirName = MailServices.ab.newAddressBook("test", "", kPABData.dirType);
let directory = MailServices.ab.getDirectoryFromId(dirName);
equal(36, directory.UID.length, "New directory has a UID");
run_next_test();
});
// Tests that an existing contact has a UID generated, and that that UID is
// saved to the database so that the same UID is used next time.
add_task(async function existingContactUID() {
- let book = MailServices.ab.getDirectory(kPABData.URI);
- let bookCards = [...book.childCards];
- equal(2, bookCards.length, "Loaded test address book");
+ let book = newAddressBookFile();
- let card = bookCards[0];
- if (card.isMailList) {
- card = bookCards[1];
- }
+ let card = [...book.childCards].find(c => !c.isMailList);
equal(36, card.UID.length, "Existing contact has a UID");
let existingUID = card.UID;
- bookCards = [...book.childCards];
- card = bookCards[0];
- if (card.isMailList) {
- card = bookCards[1];
- }
+ card = [...book.childCards].find(c => !c.isMailList);
equal(existingUID, card.UID, "New reference to contact has the same UID");
- let abFile = profD.clone();
- abFile.append(kPABData.fileName);
- let response = await fetch(Services.io.newFileURI(abFile).spec);
- let text = await response.text();
-
- ok(text.includes(card.UID), "UID has been saved to file");
+ await checkFileForUID(card.UID, book.fileName);
});
// Tests that new contacts have UIDs. Do this test last so we don't muck up
// the others by adding new things to the address book.
-add_test(function newContactUID() {
- let book = MailServices.ab.getDirectory(kPABData.URI);
+add_task(async function newContactUID() {
+ let book = newAddressBookFile();
+
let contact = Cc["@mozilla.org/addressbook/cardproperty;1"].createInstance(Ci.nsIAbCard);
let newContact = book.addCard(contact);
equal(36, newContact.UID.length, "New contact has a UID");
- run_next_test();
+ await checkFileForUID(newContact.UID, book.fileName);
+});
+
+// Tests that existing lists have UIDs. Reference the nsIAbCard first.
+add_task(async function existingListUID1() {
+ let book = newAddressBookFile();
+
+ let card = [...book.childCards].find(c => c.isMailList);
+ equal(36, card.UID.length, "Existing list's card has a UID");
+
+ let directory = MailServices.ab.getDirectory(card.mailListURI);
+ equal(36, directory.UID.length, "Existing list's directory has a UID");
+
+ equal(card.UID, directory.UID, "Existing list's card and directory UIDs match");
+
+ await checkFileForUID(card.UID, book.fileName);
+});
+
+// Tests that existing lists have UIDs. Reference the nsIAbDirectory first.
+add_task(async function existingListUID2() {
+ let book = newAddressBookFile();
+
+ let directory = MailServices.ab.getDirectory(`${book.URI}/MailList1`);
+ equal(36, directory.UID.length, "Existing list's directory has a UID");
+
+ let card = [...book.childCards].find(c => c.isMailList);
+ equal(36, card.UID.length, "Existing list's card has a UID");
+
+ equal(card.UID, directory.UID, "Existing list's card and directory UIDs match");
+
+ await checkFileForUID(card.UID, book.fileName);
});
// Tests that new lists have UIDs.
-add_test(function listUID() {
- let book = MailServices.ab.getDirectory(kPABData.URI);
- let lists = book.addressLists;
- equal(1, lists.length);
+add_task(async function newListUID() {
+ let book = newAddressBookFile();
+
+ let list = Cc["@mozilla.org/addressbook/directoryproperty;1"].createInstance(Ci.nsIAbDirectory);
+ list = book.addMailList(list);
+
+ equal(36, list.UID.length, "New list's directory has a UID");
+ equal(list.UID, MailServices.ab.getDirectory(list.URI).UID, "New reference to list's directory has the same UID");
- let directory = lists.GetElementAt(0);
- directory.QueryInterface(Ci.nsIAbDirectory);
- equal(36, directory.UID.length, "Existing list's directory has a UID");
+ let bookCards = [...book.childNodes];
+ ok(!!bookCards.find(c => c.UID == list.UID, "New reference to list has the same UID"));
+
+ await checkFileForUID(list.UID, book.fileName);
+});
+
+// 3 seems to be the lowest number that works here. I don't know why.
+var count = 3;
+function newAddressBookFile() {
+ let foo = MailServices.ab.newAddressBook(`book${count}`, `moz-abmdbdirectory://abook-${count}.mab`, 2);
- let list = Cc["@mozilla.org/addressbook/directoryproperty;1"].createInstance();
- list.QueryInterface(Ci.nsIAbDirectory);
- list.isMailList = true;
- book.addMailList(list);
- equal(2, lists.length);
+ let testAB = do_get_file("data/existing.mab");
+ testAB.copyTo(profD, `abook-${count}.mab`);
+
+ Services.prefs.setCharPref(`ldap_2.servers.book${count}.filename`, `abook-${count}.mab`);
+
+ let book = MailServices.ab.getDirectory(`moz-abmdbdirectory://abook-${count}.mab`);
+ equal(2, [...book.childCards].length);
- let newDirectory = lists.GetElementAt(1);
- newDirectory.QueryInterface(Ci.nsIAbDirectory);
- equal(36, newDirectory.UID.length, "New list's directory has a UID");
+ count++;
+ return book;
+}
- run_next_test();
-});
+async function checkFileForUID(needle, bookFileName) {
+ let abFile = profD.clone();
+ abFile.append(bookFileName);
+ let response = await fetch(Services.io.newFileURI(abFile).spec);
+ let text = await response.text();
+
+ ok(text.includes(needle), "UID has been saved to file");
+}