diff --git a/xpcom/components/nsCategoryManager.cpp b/xpcom/components/nsCategoryManager.cpp index 6efed14e216c..4e2946e5100d 100644 --- a/xpcom/components/nsCategoryManager.cpp +++ b/xpcom/components/nsCategoryManager.cpp @@ -624,16 +624,28 @@ nsCategoryManager::AddCategoryEntry( const char *aCategoryName, 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; diff --git a/xpcom/tests/unit/test_bug374754.js b/xpcom/tests/unit/test_bug374754.js new file mode 100644 index 000000000000..f0cf04d8fc80 --- /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); +}