Bug 374754 - nsCategoryManager::AddCategoryEntry should notify about removal of the previous value, patch by Wladimir Palant <trev.moz@adblockplus.org>, r+sr=darin
authorphilringnalda@gmail.com
Sun, 10 Jun 2007 23:10:27 -0700
changeset 2262 5ccabcf17d88670bf232fca6c23201e70c388dc8
parent 2261 64d18d4a7eecf0fbd1273914fa9bc49a2e99e150
child 2263 f3e70536bd1a2824ae53644c82cfbef605ef64ec
push idunknown
push userunknown
push dateunknown
bugs374754
milestone1.9a6pre
Bug 374754 - nsCategoryManager::AddCategoryEntry should notify about removal of the previous value, patch by Wladimir Palant <trev.moz@adblockplus.org>, r+sr=darin
xpcom/components/nsCategoryManager.cpp
xpcom/tests/unit/test_bug374754.js
--- a/xpcom/components/nsCategoryManager.cpp
+++ b/xpcom/components/nsCategoryManager.cpp
@@ -619,26 +619,38 @@ nsCategoryManager::AddCategoryEntry( con
     char* categoryName = ArenaStrdup(aCategoryName, &mArena);
     mTable.Put(categoryName, category);
   }
   PR_Unlock(mLock);
 
   if (!category)
     return NS_ERROR_OUT_OF_MEMORY;
 
+  // We will need the return value of AddLeaf even if the called doesn't want it
+  char *oldEntry = nsnull;
+
   nsresult rv = category->AddLeaf(aEntryName,
                                   aValue,
                                   aPersist,
                                   aReplace,
-                                  _retval,
+                                  &oldEntry,
                                   &mArena);
 
   if (NS_SUCCEEDED(rv)) {
+    if (oldEntry) {
+      NotifyObservers(NS_XPCOM_CATEGORY_ENTRY_REMOVED_OBSERVER_ID,
+                      aCategoryName, oldEntry);
+    }
     NotifyObservers(NS_XPCOM_CATEGORY_ENTRY_ADDED_OBSERVER_ID,
                     aCategoryName, aEntryName);
+
+    if (_retval)
+      *_retval = oldEntry;
+    else if (oldEntry)
+      nsMemory::Free(oldEntry);
   }
 
   return rv;
 }
 
 NS_IMETHODIMP
 nsCategoryManager::DeleteCategoryEntry( const char *aCategoryName,
                                         const char *aEntryName,
new file mode 100644
--- /dev/null
+++ b/xpcom/tests/unit/test_bug374754.js
@@ -0,0 +1,58 @@
+const Cc = Components.classes;
+const Ci = Components.interfaces;
+
+var addedTopic = "xpcom-category-entry-added";
+var removedTopic = "xpcom-category-entry-removed";
+var testCategory = "bug-test-category";
+var testEntry = "@mozilla.org/bug-test-entry;1";
+
+var result = "";
+var expected = "add remove add remove ";
+var timer;
+
+var observer = {
+  QueryInterface: function(iid) {
+    if (iid.equals(Ci.nsISupports) || iid.equals(Ci.nsIObserver))
+      return this;
+
+    throw Components.results.NS_ERROR_NO_INTERFACE;
+  },
+
+  observe: function(subject, topic, data) {
+    if (topic == "timer-callback") {
+      do_check_eq(result, expected);
+
+      var observerService = Cc["@mozilla.org/observer-service;1"].getService(Ci.nsIObserverService);
+      observerService.removeObserver(this, addedTopic);
+      observerService.removeObserver(this, removedTopic);
+
+      do_test_finished();
+
+      timer = null;
+    }
+
+    if (subject.QueryInterface(Ci.nsISupportsCString).data != testEntry || data != testCategory)
+      return;
+
+    if (topic == addedTopic)
+      result += "add ";
+    else if (topic == removedTopic)
+      result += "remove ";
+  }
+};
+
+function run_test() {
+  do_test_pending();
+
+  var observerService = Cc["@mozilla.org/observer-service;1"].getService(Ci.nsIObserverService);
+  observerService.addObserver(observer, addedTopic, false);
+  observerService.addObserver(observer, removedTopic, false);
+
+  var categoryManager = Cc["@mozilla.org/categorymanager;1"].getService(Ci.nsICategoryManager);
+  categoryManager.addCategoryEntry(testCategory, testEntry, testEntry, false, true);
+  categoryManager.addCategoryEntry(testCategory, testEntry, testEntry, false, true);
+  categoryManager.deleteCategoryEntry(testCategory, testEntry, false);
+
+  timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
+  timer.init(observer, 0, timer.TYPE_ONE_SHOT);
+}