Bug 579487 - Better error reporting when NS_CreateServicesFromCategory can't find a contract (especially to help extension developers with profile-after-change issues), r=Mossop
authorBenjamin Smedberg <benjamin@smedbergs.us>
Tue, 20 Jul 2010 09:28:45 -0400
changeset 47977 c271aa43c7ab463f949b0e16ba21bb7576ed2c56
parent 47976 c71dba463f85a43a33c44e7106950b98dba3e839
child 47978 892b780042bf8b4a6fbb8bbd319ab1d07b808903
push idunknown
push userunknown
push dateunknown
reviewersMossop
bugs579487
milestone2.0b2pre
Bug 579487 - Better error reporting when NS_CreateServicesFromCategory can't find a contract (especially to help extension developers with profile-after-change issues), r=Mossop
xpcom/components/nsCategoryManager.cpp
xpcom/components/nsCategoryManagerUtils.h
--- a/xpcom/components/nsCategoryManager.cpp
+++ b/xpcom/components/nsCategoryManager.cpp
@@ -58,16 +58,17 @@
 #include "nsReadableUtils.h"
 #include "nsCRT.h"
 #include "nsQuickSort.h"
 #include "nsEnumeratorUtils.h"
 #include "nsIProxyObjectManager.h"
 #include "nsThreadUtils.h"
 #include "mozilla/Services.h"
 
+#include "ManifestParser.h"
 #include "mozilla/FunctionTimer.h"
 
 using namespace mozilla;
 class nsIComponentLoaderManager;
 
 /*
   CategoryDatabase
   contains 0 or more 1-1 mappings of string to Category
@@ -736,66 +737,71 @@ nsCategoryManager::SuppressNotifications
  * CreateServicesFromCategory()
  *
  * Given a category, this convenience functions enumerates the category and 
  * creates a service of every CID or ContractID registered under the category.
  * If observerTopic is non null and the service implements nsIObserver,
  * this will attempt to notify the observer with the origin, observerTopic string
  * as parameter.
  */
-NS_COM nsresult
+NS_COM void
 NS_CreateServicesFromCategory(const char *category,
                               nsISupports *origin,
                               const char *observerTopic)
 {
-    NS_TIME_FUNCTION_FMT("NS_CreateServicesFromCategory: %s (%s)", category, observerTopic ? observerTopic : "(no topic)");
+  NS_TIME_FUNCTION_FMT("NS_CreateServicesFromCategory: %s (%s)",
+                       category, observerTopic ? observerTopic : "(no topic)");
+
+  nsresult rv;
+
+  nsCOMPtr<nsICategoryManager> categoryManager = 
+    do_GetService("@mozilla.org/categorymanager;1");
+  if (!categoryManager)
+    return;
 
-    nsresult rv = NS_OK;
-    
-    int nFailed = 0; 
-    nsCOMPtr<nsICategoryManager> categoryManager = 
-        do_GetService("@mozilla.org/categorymanager;1", &rv);
-    if (!categoryManager) return rv;
+  nsCOMPtr<nsISimpleEnumerator> enumerator;
+  rv = categoryManager->EnumerateCategory(category, 
+                                          getter_AddRefs(enumerator));
+  if (NS_FAILED(rv))
+    return;
 
-    nsCOMPtr<nsISimpleEnumerator> enumerator;
-    rv = categoryManager->EnumerateCategory(category, 
-            getter_AddRefs(enumerator));
-    if (NS_FAILED(rv)) return rv;
+  nsCOMPtr<nsIUTF8StringEnumerator> senumerator =
+    do_QueryInterface(enumerator);
+  if (!senumerator) {
+    NS_WARNING("Category enumerator doesn't support nsIUTF8StringEnumerator.");
+    return;
+  }
 
-    nsCOMPtr<nsISupports> entry;
-    while (NS_SUCCEEDED(enumerator->GetNext(getter_AddRefs(entry)))) {
-        // From here on just skip any error we get.
-        nsCOMPtr<nsISupportsCString> catEntry = do_QueryInterface(entry, &rv);
-        if (NS_FAILED(rv)) {
-            nFailed++;
-            continue;
-        }
-        nsCAutoString entryString;
-        rv = catEntry->GetData(entryString);
-        if (NS_FAILED(rv)) {
-            nFailed++;
-            continue;
-        }
-        nsXPIDLCString contractID;
-        rv = categoryManager->GetCategoryEntry(category,entryString.get(), getter_Copies(contractID));
-        if (NS_FAILED(rv)) {
-            nFailed++;
-            continue;
-        }
+  PRBool hasMore;
+  while (NS_SUCCEEDED(senumerator->HasMore(&hasMore)) && hasMore) {
+    // From here on just skip any error we get.
+    nsCAutoString entryString;
+    if (NS_FAILED(senumerator->GetNext(entryString)))
+      continue;
+      
+    nsXPIDLCString contractID;
+    rv = categoryManager->GetCategoryEntry(category,entryString.get(),
+                                           getter_Copies(contractID));
+    if (NS_FAILED(rv))
+      continue;
         
-        nsCOMPtr<nsISupports> instance = do_GetService(contractID, &rv);
-        if (NS_FAILED(rv)) {
-            nFailed++;
-            continue;
-        }
+    NS_TIME_FUNCTION_MARK("getservice: %s", contractID.get());
 
-        NS_TIME_FUNCTION_MARK("service: %s", nsPromiseFlatCString(contractID).get());
+    nsCOMPtr<nsISupports> instance = do_GetService(contractID);
+    if (!instance) {
+      LogMessage("While creating services from category '%s', could not create service for entry '%s', contract ID '%s'",
+                 category, entryString.get(), contractID.get());
+      continue;
+    }
 
-        if (observerTopic) {
-            // try an observer, if it implements it.
-            nsCOMPtr<nsIObserver> observer = do_QueryInterface(instance, &rv);
-            if (NS_SUCCEEDED(rv) && observer)
-                observer->Observe(origin, observerTopic, EmptyString().get());
-            NS_TIME_FUNCTION_MARK(" & observe %s", observerTopic);
-        }
+    if (observerTopic) {
+      NS_TIME_FUNCTION_MARK("observe: %s", contractID.get());
+
+      // try an observer, if it implements it.
+      nsCOMPtr<nsIObserver> observer = do_QueryInterface(instance);
+      if (observer)
+        observer->Observe(origin, observerTopic, EmptyString().get());
+      else
+        LogMessage("While creating services from category '%s', service for entry '%s', contract ID '%s' does not implement nsIObserver.",
+                   category, entryString.get(), contractID.get());
     }
-    return (nFailed ? NS_ERROR_FAILURE : NS_OK);
+  }
 }
--- a/xpcom/components/nsCategoryManagerUtils.h
+++ b/xpcom/components/nsCategoryManagerUtils.h
@@ -35,14 +35,14 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef nsCategoryManagerUtils_h__
 #define nsCategoryManagerUtils_h__
 
 #include "nsICategoryManager.h"
 
-NS_COM nsresult
+NS_COM void
 NS_CreateServicesFromCategory(const char *category,
                               nsISupports *origin,
                               const char *observerTopic);
 
 #endif