Bug 466622. Replace nsCStringArray with nsTArray<nsCString> for more consistent code and fewer heap allocations. r+sr=roc,r=bsmedberg
authorFred Jendrzejewski <fred.jen@web.de>
Thu, 22 Jan 2009 17:15:34 +1300
changeset 24031 d001c3ce1598df1c0a348112292d328cd5f2c8d7
parent 24030 7ab2054c76800cd044ee277b08285f526a597318
child 24032 23105976dd377592dae6f171224c4c37c62615fa
push idunknown
push userunknown
push dateunknown
reviewersbsmedberg
bugs466622
milestone1.9.2a1pre
Bug 466622. Replace nsCStringArray with nsTArray<nsCString> for more consistent code and fewer heap allocations. r+sr=roc,r=bsmedberg
chrome/src/nsChromeRegistry.cpp
chrome/src/nsChromeRegistry.h
content/base/public/nsIXPathEvaluatorInternal.h
content/html/content/src/nsHTMLScriptElement.cpp
content/xslt/src/main/transformiix.cpp
content/xslt/src/xpath/nsXPathEvaluator.cpp
content/xslt/src/xpath/nsXPathEvaluator.h
embedding/components/webbrowserpersist/src/nsWebBrowserPersist.cpp
embedding/components/webbrowserpersist/src/nsWebBrowserPersist.h
extensions/cookie/nsPermissionManager.cpp
extensions/spellcheck/src/mozSpellChecker.cpp
gfx/src/psshared/nsPSPrinters.cpp
gfx/src/psshared/nsPSPrinters.h
gfx/thebes/src/gfxFontconfigUtils.cpp
gfx/thebes/src/gfxFontconfigUtils.h
intl/uconv/src/nsCharsetConverterManager.cpp
intl/uconv/tests/TestUConv.cpp
intl/unicharutil/src/nsSaveAsCharset.cpp
intl/unicharutil/src/nsSaveAsCharset.h
modules/libjar/nsJARInputStream.cpp
modules/libjar/nsJARInputStream.h
modules/libpref/src/nsPrefBranch.cpp
modules/libpref/src/nsPrefBranch.h
netwerk/base/src/nsIOService.cpp
netwerk/base/src/nsURLHelperOSX.cpp
netwerk/streamconv/src/nsStreamConverterService.cpp
netwerk/streamconv/src/nsStreamConverterService.h
storage/src/mozStorageStatement.cpp
storage/src/mozStorageStatement.h
toolkit/components/url-classifier/src/nsUrlClassifierDBService.cpp
toolkit/components/url-classifier/src/nsUrlClassifierUtils.cpp
tools/trace-malloc/types.dat
uriloader/exthandler/nsMIMEInfoImpl.cpp
uriloader/exthandler/nsMIMEInfoImpl.h
widget/src/gtk2/nsDeviceContextSpecG.cpp
widget/src/gtk2/nsFilePicker.cpp
widget/src/gtk2/nsFilePicker.h
widget/src/gtk2/nsWindow.cpp
widget/src/gtk2/nsWindow.h
widget/src/qt/nsFilePicker.cpp
widget/src/qt/nsFilePicker.h
widget/src/qt/nsWindow.cpp
widget/src/qt/nsWindow.h
xpcom/base/nsCycleCollector.cpp
xpcom/ds/nsINIParserImpl.cpp
xpcom/ds/nsStringEnumerator.cpp
xpcom/ds/nsStringEnumerator.h
xpcom/glue/nsStringAPI.cpp
xpcom/glue/nsStringAPI.h
xpcom/glue/nsVoidArray.cpp
xpcom/glue/nsVoidArray.h
xpcom/string/public/nsReadableUtils.h
xpcom/string/src/nsReadableUtils.cpp
xpcom/tests/TestStrings.cpp
xpcom/tests/external/TestMinStringAPI.cpp
xpfe/components/intl/nsCharsetMenu.cpp
--- a/chrome/src/nsChromeRegistry.cpp
+++ b/chrome/src/nsChromeRegistry.cpp
@@ -332,22 +332,22 @@ nsChromeRegistry::nsProviderArray::SetBa
   provider = new ProviderEntry(aProvider, aBaseURL);
   if (!provider)
     return; // It's safe to silently fail on OOM
 
   mArray.AppendElement(provider);
 }
 
 void
-nsChromeRegistry::nsProviderArray::EnumerateToArray(nsCStringArray *a)
+nsChromeRegistry::nsProviderArray::EnumerateToArray(nsTArray<nsCString> *a)
 {
   PRInt32 i = mArray.Count();
   while (i--) {
     ProviderEntry *entry = reinterpret_cast<ProviderEntry*>(mArray[i]);
-    a->AppendCString(entry->provider);
+    a->AppendElement(entry->provider);
   }
 }
 
 void
 nsChromeRegistry::nsProviderArray::Clear()
 {
   PRInt32 i = mArray.Count();
   while (i--) {
@@ -821,17 +821,17 @@ nsChromeRegistry::GetSelectedLocale(cons
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsChromeRegistry::GetLocalesForPackage(const nsACString& aPackage,
                                        nsIUTF8StringEnumerator* *aResult)
 {
-  nsCStringArray *a = new nsCStringArray;
+  nsTArray<nsCString> *a = new nsTArray<nsCString>;
   if (!a)
     return NS_ERROR_OUT_OF_MEMORY;
 
   PackageEntry* entry =
     static_cast<PackageEntry*>(PL_DHashTableOperate(&mPackagesHash,
                                                        & aPackage,
                                                        PL_DHASH_LOOKUP));
 
--- a/chrome/src/nsChromeRegistry.h
+++ b/chrome/src/nsChromeRegistry.h
@@ -48,16 +48,17 @@
 
 #include "pldhash.h"
 
 #include "nsCOMArray.h"
 #include "nsString.h"
 #include "nsTHashtable.h"
 #include "nsURIHashKey.h"
 #include "nsVoidArray.h"
+#include "nsTArray.h"
 #include "nsInterfaceHashtable.h"
 
 struct PRFileDesc;
 class nsIAtom;
 class nsICSSLoader;
 class nsICSSStyleSheet;
 class nsIDOMWindowInternal;
 class nsILocalFile;
@@ -159,17 +160,17 @@ public:
       EXACT = 0,
       LOCALE = 1, // "en-GB" is selected, we found "en-US"
       ANY = 2
     };
 
     nsIURI* GetBase(const nsACString& aPreferred, MatchType aType);
     const nsACString& GetSelected(const nsACString& aPreferred, MatchType aType);
     void    SetBase(const nsACString& aProvider, nsIURI* base);
-    void    EnumerateToArray(nsCStringArray *a);
+    void    EnumerateToArray(nsTArray<nsCString> *a);
     void    Clear();
 
   private:
     ProviderEntry* GetProvider(const nsACString& aPreferred, MatchType aType);
 
     nsVoidArray mArray;
   };
 
--- a/content/base/public/nsIXPathEvaluatorInternal.h
+++ b/content/base/public/nsIXPathEvaluatorInternal.h
@@ -59,17 +59,17 @@ public:
   /**
    * Sets the document this evaluator corresponds to
    */
   NS_IMETHOD SetDocument(nsIDOMDocument* aDocument) = 0;
 
   NS_IMETHOD CreateExpression(const nsAString &aExpression,
                               nsIDOMXPathNSResolver *aResolver,
                               nsTArray<nsString> *aNamespaceURIs,
-                              nsCStringArray *aContractIDs,
+                              nsTArray<nsCString> *aContractIDs,
                               nsCOMArray<nsISupports> *aState,
                               nsIDOMXPathExpression **aResult) = 0;
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(nsIXPathEvaluatorInternal,
                               NS_IXPATHEVALUATORINTERNAL_IID)
 
 #endif //nsIXPathEvaluatorInternal_h__
--- a/content/html/content/src/nsHTMLScriptElement.cpp
+++ b/content/html/content/src/nsHTMLScriptElement.cpp
@@ -77,17 +77,17 @@ public:
   // Helper method called by nsHTMLScriptElement
   nsresult ParseEventString(const nsAString &aValue);
 
 protected:
   // WEAK reference to outer object.
   nsIDOMHTMLScriptElement *mOuter;
 
   // Javascript argument names must be ASCII...
-  nsCStringArray mArgNames;
+  nsTArray<nsCString> mArgNames;
 
   // The event name is kept UCS2 for 'quick comparisions'...
   nsString mEventName;
 };
 
 
 nsHTMLScriptEventHandler::nsHTMLScriptEventHandler(nsIDOMHTMLScriptElement *aOuter)
 {
@@ -139,17 +139,17 @@ nsresult nsHTMLScriptEventHandler::Parse
     // The arguments are not enclosed in parentheses...
     return NS_ERROR_FAILURE;
   }
 
   // Javascript expects all argument names to be ASCII.
   NS_LossyConvertUTF16toASCII sig(Substring(next, end));
 
   // Store each (comma separated) argument in mArgNames
-  mArgNames.ParseString(sig.get(), ",");
+  ParseString(sig, ',', mArgNames);
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsHTMLScriptEventHandler::IsSameEvent(const nsAString &aObjectName,
                                       const nsAString &aEventName,
                                       PRUint32 aArgCount,
@@ -252,27 +252,27 @@ nsHTMLScriptEventHandler::Invoke(nsISupp
   //
   const int kMaxArgsOnStack = 10;
 
   PRInt32 argc, i;
   const char** args;
   const char*  stackArgs[kMaxArgsOnStack];
 
   args = stackArgs;
-  argc = mArgNames.Count();
+  argc = PRInt32(mArgNames.Length());
 
   // If there are too many arguments then allocate the array from the heap
   // otherwise build it up on the stack...
   if (argc >= kMaxArgsOnStack) {
     args = new const char*[argc+1];
     if (!args) return NS_ERROR_OUT_OF_MEMORY;
   }
 
   for(i=0; i<argc; i++) {
-    args[i] = mArgNames[i]->get();
+    args[i] = mArgNames[i].get();
   }
 
   // Null terminate for good luck ;-)
   args[i] = nsnull;
 
   // Compile the event handler script...
   void* funcObject = nsnull;
   NS_NAMED_LITERAL_CSTRING(funcName, "anonymous");
--- a/content/xslt/src/main/transformiix.cpp
+++ b/content/xslt/src/main/transformiix.cpp
@@ -34,17 +34,17 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "txStandaloneXSLTProcessor.h"
 #include "nsXPCOM.h"
 #include <fstream.h>
 #include "nsDoubleHashtable.h"
-#include "nsVoidArray.h"
+#include "nsTArray.h"
 #ifdef MOZ_JPROF
 #include "jprof.h"
 #endif
 
 /**
  * Prints the command line help screen to the console
  */
 void printHelp()
@@ -73,17 +73,17 @@ void printUsage()
 }
 
 class txOptionEntry : public PLDHashCStringEntry
 {
 public:
     txOptionEntry(const void* aKey) : PLDHashCStringEntry(aKey)
     {
     }
-    nsCStringArray mValues;
+    nsTArray<nsCString> mValues;
 };
 
 DECL_DHASH_WRAPPER(txOptions, txOptionEntry, nsACString&)
 DHASH_WRAPPER(txOptions, txOptionEntry, nsACString&)
 
 /**
  * Parses the command line
  */
@@ -101,17 +101,17 @@ void parseCommandLine(int argc, char** a
             }
 
             // get next flag
             flag = Substring(arg, 1, arg.Length() - 1);
         }
         else {
             txOptionEntry* option = aOptions.AddEntry(flag);
             if (option) {
-                option->mValues.AppendCString(nsCString(arg));
+                option->mValues.AppendElement(nsCString(arg));
             }
             flag.Truncate();
         }
     }
 
     if (!flag.IsEmpty()) {
         aOptions.AddEntry(flag);
     }
@@ -158,44 +158,44 @@ int main(int argc, char** argv)
     }
 
     //-- handle output stream
     ostream* resultOutput = &cout;
     ofstream resultFileStream;
 
     txOptionEntry* option = options.GetEntry(NS_LITERAL_CSTRING("o"));
     if (option &&
-        option->mValues.Count() > 0 &&
-        !option->mValues[0]->EqualsLiteral("-")) {
-        resultFileStream.open(option->mValues[0]->get(), ios::out);
+        option->mValues.Length() > 0 &&
+        !option->mValues[0].EqualsLiteral("-")) {
+        resultFileStream.open(option->mValues[0].get(), ios::out);
         if (!resultFileStream) {
             cerr << "error opening output file: ";
-            cerr << option->mValues[0]->get() << endl;
+            cerr << option->mValues[0].get() << endl;
             return -1;
         }
         resultOutput = &resultFileStream;
     }
 
     option = options.GetEntry(NS_LITERAL_CSTRING("i"));
-    if (!option || option->mValues.Count() == 0) {
+    if (!option || option->mValues.Length() == 0) {
         cerr << "you must specify at least a source XML path" << endl;
         printUsage();
         return -1;
     }
 
     SimpleErrorObserver obs;
     txStandaloneXSLTProcessor proc;
 
     txOptionEntry* styleOption = options.GetEntry(NS_LITERAL_CSTRING("s"));
-    if (!styleOption || styleOption->mValues.Count() == 0) {
-        rv = proc.transform(*option->mValues[0], *resultOutput, obs);
+    if (!styleOption || styleOption->mValues.Length() == 0) {
+        rv = proc.transform(option->mValues[0], *resultOutput, obs);
     }
     else {
         // XXX TODO: Handle multiple stylesheets
-        rv = proc.transform(*option->mValues[0], *styleOption->mValues[0],
+        rv = proc.transform(option->mValues[0], styleOption->mValues[0],
                             *resultOutput, obs);
     }
 
     if (NS_FAILED(rv)) {
         cerr << "transformation failed with " << hex << rv << endl;
     }
 
     resultFileStream.close();
--- a/content/xslt/src/xpath/nsXPathEvaluator.cpp
+++ b/content/xslt/src/xpath/nsXPathEvaluator.cpp
@@ -57,17 +57,17 @@
 
 // txIParseContext implementation
 class nsXPathEvaluatorParseContext : public txIParseContext
 {
 public:
     nsXPathEvaluatorParseContext(nsXPathEvaluator &aEvaluator,
                                  nsIDOMXPathNSResolver* aResolver,
                                  nsTArray<PRInt32> *aNamespaceIDs,
-                                 nsCStringArray *aContractIDs,
+                                 nsTArray<nsCString> *aContractIDs,
                                  nsCOMArray<nsISupports> *aState,
                                  PRBool aIsCaseSensitive)
         : mEvaluator(aEvaluator),
           mResolver(aResolver),
           mNamespaceIDs(aNamespaceIDs),
           mContractIDs(aContractIDs),
           mState(aState),
           mLastError(NS_OK),
@@ -88,17 +88,17 @@ public:
                                  FunctionCall** aFunction);
     PRBool caseInsensitiveNameTests();
     void SetErrorOffset(PRUint32 aOffset);
 
 private:
     nsXPathEvaluator &mEvaluator;
     nsIDOMXPathNSResolver* mResolver;
     nsTArray<PRInt32> *mNamespaceIDs;
-    nsCStringArray *mContractIDs;
+    nsTArray<nsCString> *mContractIDs;
     nsCOMArray<nsISupports> *mState;
     nsresult mLastError;
     PRBool mIsCaseSensitive;
 };
 
 NS_IMPL_AGGREGATED(nsXPathEvaluator)
 NS_INTERFACE_MAP_BEGIN_AGGREGATED(nsXPathEvaluator)
     NS_INTERFACE_MAP_ENTRY(nsIDOMXPathEvaluator)
@@ -166,52 +166,52 @@ nsXPathEvaluator::SetDocument(nsIDOMDocu
     mDocument = do_GetWeakReference(aDocument);
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsXPathEvaluator::CreateExpression(const nsAString & aExpression,
                                    nsIDOMXPathNSResolver *aResolver,
                                    nsTArray<nsString> *aNamespaceURIs,
-                                   nsCStringArray *aContractIDs,
+                                   nsTArray<nsCString> *aContractIDs,
                                    nsCOMArray<nsISupports> *aState,
                                    nsIDOMXPathExpression **aResult)
 {
     nsTArray<PRInt32> namespaceIDs;
     if (aNamespaceURIs) {
         PRUint32 count = aNamespaceURIs->Length();
 
-        if (!aContractIDs || aContractIDs->Count() != count) {
+        if (!aContractIDs || aContractIDs->Length() != count) {
             return NS_ERROR_FAILURE;
         }
 
         if (!namespaceIDs.SetLength(count)) {
             return NS_ERROR_OUT_OF_MEMORY;
         }
 
         PRUint32 i;
         for (i = 0; i < count; ++i) {
-            if (aContractIDs->CStringAt(i)->IsEmpty()) {
+            if (aContractIDs->ElementAt(i).IsEmpty()) {
                 return NS_ERROR_FAILURE;
             }
 
             nsContentUtils::NameSpaceManager()->RegisterNameSpace(aNamespaceURIs->ElementAt(i), namespaceIDs[i]);
         }
     }
 
 
     return CreateExpression(aExpression, aResolver, &namespaceIDs, aContractIDs,
                             aState, aResult);
 }
 
 nsresult
 nsXPathEvaluator::CreateExpression(const nsAString & aExpression,
                                    nsIDOMXPathNSResolver *aResolver,
                                    nsTArray<PRInt32> *aNamespaceIDs,
-                                   nsCStringArray *aContractIDs,
+                                   nsTArray<nsCString> *aContractIDs,
                                    nsCOMArray<nsISupports> *aState,
                                    nsIDOMXPathExpression **aResult)
 {
     nsresult rv;
     if (!mRecycler) {
         nsRefPtr<txResultRecycler> recycler = new txResultRecycler;
         NS_ENSURE_TRUE(recycler, NS_ERROR_OUT_OF_MEMORY);
         
@@ -296,17 +296,17 @@ nsXPathEvaluatorParseContext::resolveFun
                                                   FunctionCall** aFn)
 {
     nsresult rv = NS_ERROR_XPATH_UNKNOWN_FUNCTION;
 
     PRUint32 i, count = mNamespaceIDs ? mNamespaceIDs->Length() : 0;
     for (i = 0; i < count; ++i) {
         if (mNamespaceIDs->ElementAt(i) == aID) {
             nsISupports *state = mState ? mState->SafeObjectAt(i) : nsnull;
-            rv = TX_ResolveFunctionCallXPCOM(*mContractIDs->CStringAt(i), aID,
+            rv = TX_ResolveFunctionCallXPCOM(mContractIDs->ElementAt(i), aID,
                                              aName, state, aFn);
             if (NS_SUCCEEDED(rv)) {
                 break;
             }
         }
     }
 
     return rv;
--- a/content/xslt/src/xpath/nsXPathEvaluator.h
+++ b/content/xslt/src/xpath/nsXPathEvaluator.h
@@ -65,25 +65,25 @@ public:
     // nsIDOMXPathEvaluator interface
     NS_DECL_NSIDOMXPATHEVALUATOR
 
     // nsIXPathEvaluatorInternal interface
     NS_IMETHOD SetDocument(nsIDOMDocument* aDocument);
     NS_IMETHOD CreateExpression(const nsAString &aExpression, 
                                 nsIDOMXPathNSResolver *aResolver,
                                 nsTArray<nsString> *aNamespaceURIs,
-                                nsCStringArray *aContractIDs,
+                                nsTArray<nsCString> *aContractIDs,
                                 nsCOMArray<nsISupports> *aState,
                                 nsIDOMXPathExpression **aResult);
 
 private:
     nsresult CreateExpression(const nsAString & aExpression,
                               nsIDOMXPathNSResolver *aResolver,
                               nsTArray<PRInt32> *aNamespaceIDs,
-                              nsCStringArray *aContractIDs,
+                              nsTArray<nsCString> *aContractIDs,
                               nsCOMArray<nsISupports> *aState,
                               nsIDOMXPathExpression **aResult);
 
     nsWeakPtr mDocument;
     nsRefPtr<txResultRecycler> mRecycler;
 };
 
 /* d0a75e02-b5e7-11d5-a7f2-df109fb8a1fc */
--- a/embedding/components/webbrowserpersist/src/nsWebBrowserPersist.cpp
+++ b/embedding/components/webbrowserpersist/src/nsWebBrowserPersist.cpp
@@ -1990,17 +1990,17 @@ nsWebBrowserPersist::CalculateUniqueFile
         filename.Append(ext);
         nameHasChanged = PR_TRUE;
     }
 
     // Ensure the filename is unique
     // Create a filename if it's empty, or if the filename / datapath is
     // already taken by another URI and create an alternate name.
 
-    if (base.IsEmpty() || mFilenameList.Count() > 0)
+    if (base.IsEmpty() || mFilenameList.Length() > 0)
     {
         nsCAutoString tmpPath;
         nsCAutoString tmpBase;
         PRUint32 duplicateCounter = 1;
         while (1)
         {
             // Make a file name,
             // Foo become foo_001, foo_002, etc.
@@ -2043,17 +2043,17 @@ nsWebBrowserPersist::CalculateUniqueFile
             }
             duplicateCounter++;
         }
     }
 
     // Add name to list of those already used
     nsCAutoString newFilepath(directory);
     newFilepath.Append(filename);
-    mFilenameList.AppendCString(newFilepath);
+    mFilenameList.AppendElement(newFilepath);
 
     // Update the uri accordingly if the filename actually changed
     if (nameHasChanged)
     {
         // Final sanity test
         if (filename.Length() > kDefaultMaxFilenameLength)
         {
             NS_WARNING("Filename wasn't truncated less than the max file length - how can that be?");
--- a/embedding/components/webbrowserpersist/src/nsWebBrowserPersist.h
+++ b/embedding/components/webbrowserpersist/src/nsWebBrowserPersist.h
@@ -53,16 +53,17 @@
 #include "nsIDocumentEncoder.h"
 #include "nsITransport.h"
 #include "nsIProgressEventSink.h"
 #include "nsILocalFile.h"
 #include "nsIWebProgressListener2.h"
 
 #include "nsHashtable.h"
 #include "nsVoidArray.h"
+#include "nsTArray.h"
 #include "nsInt64.h"
 
 #include "nsCWebBrowserPersist.h"
 
 class nsEncoderNodeFixup;
 class nsIStorageStream;
 
 struct URIData;
@@ -221,17 +222,17 @@ private:
      */
     nsCOMPtr<nsIWebProgressListener2> mProgressListener2;
     nsCOMPtr<nsIProgressEventSink> mEventSink;
     nsHashtable               mOutputMap;
     nsHashtable               mUploadList;
     nsHashtable               mURIMap;
     nsVoidArray               mDocList;
     nsVoidArray               mCleanupList;
-    nsCStringArray            mFilenameList;
+    nsTArray<nsCString>       mFilenameList;
     PRPackedBool              mFirstAndOnlyUse;
     PRPackedBool              mCancel;
     PRPackedBool              mJustStartedLoading;
     PRPackedBool              mCompleted;
     PRPackedBool              mStartSaving;
     PRPackedBool              mReplaceExisting;
     PRPackedBool              mSerializingOutput;
     PRUint32                  mPersistFlags;
--- a/extensions/cookie/nsPermissionManager.cpp
+++ b/extensions/cookie/nsPermissionManager.cpp
@@ -38,16 +38,18 @@
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsPermissionManager.h"
 #include "nsPermission.h"
 #include "nsCRT.h"
 #include "nsNetUtil.h"
 #include "nsCOMArray.h"
 #include "nsArrayEnumerator.h"
+#include "nsTArray.h"
+#include "nsReadableUtils.h"
 #include "nsILineInputStream.h"
 #include "nsIIDNService.h"
 #include "nsAppDirectoryServiceDefs.h"
 #include "prprf.h"
 #include "mozIStorageService.h"
 #include "mozIStorageStatement.h"
 #include "mozIStorageConnection.h"
 #include "mozStorageHelper.h"
@@ -738,37 +740,37 @@ nsPermissionManager::Import()
 
   nsCAutoString buffer;
   PRBool isMore = PR_TRUE;
   while (isMore && NS_SUCCEEDED(lineInputStream->ReadLine(buffer, &isMore))) {
     if (buffer.IsEmpty() || buffer.First() == '#') {
       continue;
     }
 
-    nsCStringArray lineArray;
+    nsTArray<nsCString> lineArray;
 
     // Split the line at tabs
-    lineArray.ParseString(buffer.get(), "\t");
+    ParseString(buffer, '\t', lineArray);
     
-    if (lineArray[0]->EqualsLiteral(kMatchTypeHost) &&
-        lineArray.Count() == 4) {
+    if (lineArray[0].EqualsLiteral(kMatchTypeHost) &&
+        lineArray.Length() == 4) {
       
       PRInt32 error;
-      PRUint32 permission = lineArray[2]->ToInteger(&error);
+      PRUint32 permission = lineArray[2].ToInteger(&error);
       if (error)
         continue;
 
       // hosts might be encoded in UTF8; switch them to ACE to be consistent
-      if (!IsASCII(*lineArray[3])) {
-        rv = NormalizeToACE(*lineArray[3]);
+      if (!IsASCII(lineArray[3])) {
+        rv = NormalizeToACE(lineArray[3]);
         if (NS_FAILED(rv))
           continue;
       }
 
-      rv = AddInternal(*lineArray[3], *lineArray[1], permission, 0, eDontNotify, eWriteToDB);
+      rv = AddInternal(lineArray[3], lineArray[1], permission, 0, eDontNotify, eWriteToDB);
       NS_ENSURE_SUCCESS(rv, rv);
     }
   }
 
   // we're done importing - delete the old file
   permissionsFile->Remove(PR_FALSE);
 
   return NS_OK;
--- a/extensions/spellcheck/src/mozSpellChecker.cpp
+++ b/extensions/spellcheck/src/mozSpellChecker.cpp
@@ -468,17 +468,17 @@ mozSpellChecker::GetCurrentBlockIndex(ns
 }
 
 nsresult
 mozSpellChecker::InitSpellCheckDictionaryMap()
 {
   nsresult rv;
   PRBool hasMoreEngines;
   PRInt32 i;
-  nsCStringArray contractIds;
+  nsTArray<nsCString> contractIds;
 
   nsCOMPtr<nsICategoryManager> catMgr = do_GetService(NS_CATEGORYMANAGER_CONTRACTID);
   if (!catMgr)
     return NS_ERROR_NULL_POINTER;
 
   nsCOMPtr<nsISimpleEnumerator> catEntries;
 
   // Get contract IDs of registrated external spell-check engines and
@@ -495,38 +495,38 @@ mozSpellChecker::InitSpellCheckDictionar
     if (NS_FAILED(rv))
       return rv;
 
     nsCString contractId;
     rv = entry->GetData(contractId);
     if (NS_FAILED(rv))
       return rv;
 
-    contractIds.AppendCString(contractId);
+    contractIds.AppendElement(contractId);
   }
 
-  contractIds.AppendCString(NS_LITERAL_CSTRING(DEFAULT_SPELL_CHECKER));
+  contractIds.AppendElement(NS_LITERAL_CSTRING(DEFAULT_SPELL_CHECKER));
 
   // Retrieve dictionaries from all available spellcheckers and
   // fill mDictionariesMap hash (only the first dictionary with the
   // each name is used).
-  for (i=0;i<contractIds.Count();i++){
+  for (i=0;i < PRInt32(contractIds.Length());i++){
     PRUint32 count,k;
     PRUnichar **words;
 
-    nsCString *contractId = contractIds[i];
+    const nsCString& contractId = contractIds[i];
 
     // Try to load spellchecker engine. Ignore errors silently
     // except for the last one (HunSpell).
     nsCOMPtr<mozISpellCheckingEngine> engine =
-      do_GetService(contractId->get(), &rv);
+      do_GetService(contractId.get(), &rv);
     if (NS_FAILED(rv)){
       // Fail if not succeeded to load HunSpell. Ignore errors
       // for external spellcheck engines.
-      if (i==contractIds.Count()-1){
+      if (i==contractIds.Length()-1){
         return rv;
       }
 
       continue;
     }
 
     engine->GetDictionaryList(&words,&count);
     for(k=0;k<count;k++){
@@ -536,16 +536,16 @@ mozSpellChecker::InitSpellCheckDictionar
 
       nsCString dictCName = NS_ConvertUTF16toUTF8(dictName);
 
       // Skip duplicate dictionaries. Only take the first one
       // for each name.
       if (mDictionariesMap.Get(dictName, NULL))
         continue;
 
-      mDictionariesMap.Put(dictName, new nsCString(*contractId));
+      mDictionariesMap.Put(dictName, new nsCString(contractId));
     }
 
     NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(count, words);
   }
 
   return NS_OK;
 }
--- a/gfx/src/psshared/nsPSPrinters.cpp
+++ b/gfx/src/psshared/nsPSPrinters.cpp
@@ -88,17 +88,17 @@ nsPSPrinterList::Enabled()
     PRBool setting = PR_TRUE;
     mPref->GetBoolPref("postscript.enabled", &setting);
     return setting;
 }
 
 
 /* Fetch a list of printers handled by the PostsScript module */
 void
-nsPSPrinterList::GetPrinterList(nsCStringArray& aList)
+nsPSPrinterList::GetPrinterList(nsTArray<nsCString>& aList)
 {
     aList.Clear();
 
     // Query CUPS for a printer list. The default printer goes to the
     // head of the output list; others are appended.
     if (mCups.IsInitialized()) {
         cups_dest_t *dests;
 
@@ -107,31 +107,31 @@ nsPSPrinterList::GetPrinterList(nsCStrin
             for (int i = 0; i < num_dests; i++) {
                 nsCAutoString fullName(NS_CUPS_PRINTER);
                 fullName.Append(dests[i].name);
                 if (dests[i].instance != NULL) {
                     fullName.Append("/");
                     fullName.Append(dests[i].instance);
                 }
                 if (dests[i].is_default)
-                    aList.InsertCStringAt(fullName, 0);
+                    aList.InsertElementAt(0, fullName);
                 else
-                    aList.AppendCString(fullName);
+                    aList.AppendElement(fullName);
             }
         }
         (mCups.mCupsFreeDests)(num_dests, dests);
     }
 
     // Build the "classic" list of printers -- those accessed by running
     // an opaque command. This list always contains a printer named "default".
     // In addition, we look for either an environment variable
     // MOZILLA_POSTSCRIPT_PRINTER_LIST or a preference setting
     // print.printer_list, which contains a space-separated list of printer
     // names.
-    aList.AppendCString(
+    aList.AppendElement(
             NS_LITERAL_CSTRING(NS_POSTSCRIPT_DRIVER_NAME "default"));
 
     nsXPIDLCString list;
     list.Assign(PR_GetEnv("MOZILLA_POSTSCRIPT_PRINTER_LIST"));
     if (list.IsEmpty())
         mPref->GetCharPref("printer_list", getter_Copies(list));
     if (!list.IsEmpty()) {
         // For each printer (except "default" which was already added),
@@ -140,17 +140,17 @@ nsPSPrinterList::GetPrinterList(nsCStrin
 
         for (char *name = PL_strtok_r(list.BeginWriting(), " ", &state);
                 nsnull != name;
                 name = PL_strtok_r(nsnull, " ", &state)
         ) {
             if (0 != strcmp(name, "default")) {
                 nsCAutoString fullName(NS_POSTSCRIPT_DRIVER_NAME);
                 fullName.Append(name);
-                aList.AppendCString(fullName);
+                aList.AppendElement(fullName);
             }
         }
     }
 }
 
 
 /* Identify the printer type */
 nsPSPrinterList::PrinterType
--- a/gfx/src/psshared/nsPSPrinters.h
+++ b/gfx/src/psshared/nsPSPrinters.h
@@ -35,17 +35,17 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef nsPSPrinters_h___
 #define nsPSPrinters_h___
 
 #include "nsString.h"
-#include "nsVoidArray.h"
+#include "nsTArray.h"
 #include "prtypes.h"
 #include "nsCUPSShim.h"
 #include "psSharedCore.h"
 
 class nsIPrefService;
 class nsIPrefBranch;
 class nsCUPSShim;
 
@@ -72,17 +72,17 @@ class NS_PSSHARED nsPSPrinterList {
          * printer name.
          *
          * @param aList Upon return, this is populated with the list of
          *              printer names as described above, replacing any
          *              previous contents. Each entry is a UTF8 string.
          *              There should always be at least one entry. The
          *              first entry is the default print destination.
          */
-        void GetPrinterList(nsCStringArray& aList);
+        void GetPrinterList(nsTArray<nsCString>& aList);
 
         enum PrinterType {
             kTypeUnknown,         // Not actually handled by the PS module
             kTypePS,              // Generic postscript module printer
             kTypeCUPS             // CUPS printer
         };
 
         /**
--- a/gfx/thebes/src/gfxFontconfigUtils.cpp
+++ b/gfx/thebes/src/gfxFontconfigUtils.cpp
@@ -273,23 +273,23 @@ gfxFontconfigUtils::gfxFontconfigUtils()
 
 nsresult
 gfxFontconfigUtils::GetFontList(const nsACString& aLangGroup,
                                 const nsACString& aGenericFamily,
                                 nsTArray<nsString>& aListOfFonts)
 {
     aListOfFonts.Clear();
 
-    nsCStringArray fonts;
+    nsTArray<nsCString> fonts;
     nsresult rv = GetFontListInternal(fonts, aLangGroup);
     if (NS_FAILED(rv))
         return rv;
 
-    for (PRInt32 i = 0; i < fonts.Count(); ++i) {
-        aListOfFonts.AppendElement(NS_ConvertUTF8toUTF16(*fonts.CStringAt(i)));
+    for (PRUint32 i = 0; i < fonts.Length(); ++i) {
+        aListOfFonts.AppendElement(NS_ConvertUTF8toUTF16(fonts[i]));
     }
 
     aListOfFonts.Sort();
 
     PRInt32 serif = 0, sansSerif = 0, monospace = 0;
 
     // Fontconfig supports 3 generic fonts, "serif", "sans-serif", and
     // "monospace", slightly different from CSS's 5.
@@ -443,17 +443,17 @@ gfxFontconfigUtils::GetSampleLangForGrou
     if (langGroup->defaultLang) {
         aFcLang->Assign(langGroup->defaultLang);
     } else {
         aFcLang->Truncate();
     }
 }
 
 nsresult
-gfxFontconfigUtils::GetFontListInternal(nsCStringArray& aListOfFonts,
+gfxFontconfigUtils::GetFontListInternal(nsTArray<nsCString>& aListOfFonts,
                                         const nsACString& aLangGroup)
 {
     FcPattern *pat = NULL;
     FcObjectSet *os = NULL;
     FcFontSet *fs = NULL;
     nsresult rv = NS_ERROR_FAILURE;
 
     aListOfFonts.Clear();
@@ -481,20 +481,20 @@ gfxFontconfigUtils::GetFontListInternal(
         if (FcPatternGetString(fs->fonts[i], FC_FAMILY, 0,
                                (FcChar8 **) &family) != FcResultMatch)
         {
             continue;
         }
 
         // Remove duplicates...
         nsCAutoString strFamily(family);
-        if (aListOfFonts.IndexOf(strFamily) >= 0)
+        if (aListOfFonts.Contains(strFamily))
             continue;
 
-        aListOfFonts.AppendCString(strFamily);
+        aListOfFonts.AppendElement(strFamily);
     }
 
     rv = NS_OK;
 
   end:
     if (NS_FAILED(rv))
         aListOfFonts.Clear();
 
@@ -598,17 +598,17 @@ gfxFontconfigUtils::UpdateFontListIntern
             }
             if (p == p_end)
                 break;
             const char *start = p;
             while (++p != p_end && *p != kComma)
                 /* nothing */ ;
             nsCAutoString name(Substring(start, p));
             name.CompressWhitespace(PR_FALSE, PR_TRUE);
-            mAliasForMultiFonts.AppendCString(name);
+            mAliasForMultiFonts.AppendElement(name);
             p++;
         }
     }
 
     mLastConfig = currentConfig;
     return NS_OK;
 }
 
@@ -633,17 +633,17 @@ gfxFontconfigUtils::GetStandardFamilyNam
 
     // return empty string if no such family exists
     if (!IsExistingFamily(fontname))
         return NS_OK;
 
     FcPattern *pat = NULL;
     FcObjectSet *os = NULL;
     FcFontSet *givenFS = NULL;
-    nsCStringArray candidates;
+    nsTArray<nsCString> candidates;
     FcFontSet *candidateFS = NULL;
     rv = NS_ERROR_FAILURE;
 
     pat = FcPatternCreate();
     if (!pat)
         goto end;
 
     FcPatternAddString(pat, FC_FAMILY, (FcChar8 *)fontname.get());
@@ -662,49 +662,49 @@ gfxFontconfigUtils::GetStandardFamilyNam
     // See if there is a font face with first family equal to the given family.
     for (int i = 0; i < givenFS->nfont; ++i) {
         char *firstFamily;
         if (FcPatternGetString(givenFS->fonts[i], FC_FAMILY, 0,
                                (FcChar8 **) &firstFamily) != FcResultMatch)
             continue;
 
         nsDependentCString first(firstFamily);
-        if (candidates.IndexOf(first) < 0) {
-            candidates.AppendCString(first);
+        if (!candidates.Contains(first)) {
+            candidates.AppendElement(first);
 
             if (fontname.Equals(first)) {
                 aFamilyName.Assign(aFontName);
                 rv = NS_OK;
                 goto end;
             }
         }
     }
 
     // See if any of the first family names represent the same set of font
     // faces as the given family.
-    for (PRInt32 j = 0; j < candidates.Count(); ++j) {
+    for (PRUint32 j = 0; j < candidates.Length(); ++j) {
         FcPatternDel(pat, FC_FAMILY);
-        FcPatternAddString(pat, FC_FAMILY, (FcChar8 *)candidates[j]->get());
+        FcPatternAddString(pat, FC_FAMILY, (FcChar8 *)candidates[j].get());
 
         candidateFS = FcFontList(NULL, pat, os);
         if (!candidateFS)
             goto end;
 
         if (candidateFS->nfont != givenFS->nfont)
             continue;
 
         PRBool equal = PR_TRUE;
         for (int i = 0; i < givenFS->nfont; ++i) {
             if (!FcPatternEqual(candidateFS->fonts[i], givenFS->fonts[i])) {
                 equal = PR_FALSE;
                 break;
             }
         }
         if (equal) {
-            AppendUTF8toUTF16(*candidates[j], aFamilyName);
+            AppendUTF8toUTF16(candidates[j], aFamilyName);
             rv = NS_OK;
             goto end;
         }
     }
 
     // No match found; return empty string.
     rv = NS_OK;
 
@@ -742,17 +742,17 @@ gfxFontconfigUtils::ResolveFontName(cons
     // check just whether the font is existing, without resolving to regular
     // name.
     //
     // The family names in mAliasForMultiFonts are names understood by
     // fontconfig.  The actual font to which they resolve depends on the
     // entire match pattern.  That info is not available here, but there
     // will be a font so leave the resolving to the gfxFontGroup.
     if (IsExistingFamily(fontname) ||
-        mAliasForMultiFonts.IndexOfIgnoreCase(fontname) != -1)
+        mAliasForMultiFonts.Contains(fontname, gfxIgnoreCaseCStringComparator()))
         aAborted = !(*aCallback)(aFontName, aClosure);
 
     return NS_OK;
 }
 
 PRBool
 gfxFontconfigUtils::IsExistingFamily(const nsCString& aFamilyName)
 {
--- a/gfx/thebes/src/gfxFontconfigUtils.h
+++ b/gfx/thebes/src/gfxFontconfigUtils.h
@@ -65,16 +65,29 @@ public:
 
 NS_SPECIALIZE_TEMPLATE
 class nsAutoRefTraits<FcCharSet> : public nsPointerRefTraits<FcCharSet>
 {
 public:
     static void Release(FcCharSet *ptr) { FcCharSetDestroy(ptr); }
 };
 
+class gfxIgnoreCaseCStringComparator
+{
+  public:
+    PRBool Equals(const nsACString& a, const nsACString& b) const
+    {
+      return nsCString(a).Equals(b, nsCaseInsensitiveCStringComparator());
+    }
+
+    PRBool LessThan(const nsACString& a, const nsACString& b) const
+    { 
+      return a < b;
+    }
+};
 
 class gfxFontNameList : public nsTArray<nsString>
 {
 public:
     THEBES_INLINE_DECL_REFCOUNTING(gfxFontNameList)
     PRBool Exists(nsAString& aName);
 };
 
@@ -303,17 +316,17 @@ protected:
         FcLangResult mSupport;
         nsTArray< nsCountedRef<FcPattern> > mFonts;
     };
 
     static gfxFontconfigUtils* sUtils;
 
     PRBool IsExistingFamily(const nsCString& aFamilyName);
 
-    nsresult GetFontListInternal(nsCStringArray& aListOfFonts,
+    nsresult GetFontListInternal(nsTArray<nsCString>& aListOfFonts,
                                  const nsACString& aLangGroup);
     nsresult UpdateFontListInternal(PRBool aForce = PR_FALSE);
 
     void AddFullnameEntries();
 
     LangSupportEntry *GetLangSupportEntry(const FcChar8 *aLang,
                                           PRBool aWithFonts);
 
@@ -322,14 +335,14 @@ protected:
     nsTHashtable<FontsByFcStrEntry> mFontsByFamily;
     nsTHashtable<FontsByFullnameEntry> mFontsByFullname;
     // mLangSupportTable contains an entry for each language that has been
     // looked up through GetLangSupportEntry, even when the language is not
     // supported.
     nsTHashtable<LangSupportEntry> mLangSupportTable;
     const nsTArray< nsCountedRef<FcPattern> > mEmptyPatternArray;
 
-    nsCStringArray mAliasForMultiFonts;
+    nsTArray<nsCString> mAliasForMultiFonts;
 
     FcConfig *mLastConfig;
 };
 
 #endif /* GFX_FONTCONFIG_UTILS_H */
--- a/intl/uconv/src/nsCharsetConverterManager.cpp
+++ b/intl/uconv/src/nsCharsetConverterManager.cpp
@@ -45,17 +45,17 @@
 #include "nsICategoryManager.h"
 #include "nsICharsetConverterManager.h"
 #include "nsEncoderDecoderUtils.h"
 #include "nsIStringBundle.h"
 #include "nsILocaleService.h"
 #include "nsUConvDll.h"
 #include "prmem.h"
 #include "nsCRT.h"
-#include "nsVoidArray.h"
+#include "nsTArray.h"
 #include "nsStringEnumerator.h"
 #include "nsThreadUtils.h"
 #include "nsIProxyObjectManager.h"
 
 #include "nsXPCOM.h"
 #include "nsISupportsPrimitives.h"
 
 // just for CONTRACTIDs
@@ -298,17 +298,17 @@ nsCharsetConverterManager::GetList(const
 
   nsresult rv;
   nsCAutoString alias;
 
   nsCOMPtr<nsICategoryManager> catman = do_GetService(NS_CATEGORYMANAGER_CONTRACTID, &rv);
   if (NS_FAILED(rv))
     return rv;
 
-  nsCStringArray* array = new nsCStringArray;
+  nsTArray<nsCString>* array = new nsTArray<nsCString>;
   if (!array)
     return NS_ERROR_OUT_OF_MEMORY;
   
   nsCOMPtr<nsISimpleEnumerator> enumerator;
   catman->EnumerateCategory(PromiseFlatCString(aCategory).get(), 
                             getter_AddRefs(enumerator));
 
   PRBool hasMore;
@@ -327,17 +327,17 @@ nsCharsetConverterManager::GetList(const
     if (NS_FAILED(supStr->GetData(name)))
       continue;
 
     fullName += name;
     rv = GetCharsetAlias(fullName.get(), alias);
     if (NS_FAILED(rv)) 
       continue;
 
-    rv = array->AppendCString(alias);
+    rv = array->AppendElement(alias) ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
   }
     
   return NS_NewAdoptingUTF8StringEnumerator(aResult, array);
 }
 
 // we should change the interface so that we can just pass back a enumerator!
 NS_IMETHODIMP
 nsCharsetConverterManager::GetDecoderList(nsIUTF8StringEnumerator ** aResult)
--- a/intl/uconv/tests/TestUConv.cpp
+++ b/intl/uconv/tests/TestUConv.cpp
@@ -35,17 +35,17 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsIServiceManager.h"
 #include "nsICharsetConverterManager.h"
 #include "nsUCSupport.h"
 #include "nsString.h"
 #include "nsIStringEnumerator.h"
-#include "nsVoidArray.h"
+#include "nsTArray.h"
 
 //----------------------------------------------------------------------------
 // Global functions and data [declaration]
 
 #define ARRAY_SIZE(_array)  (sizeof(_array) / sizeof(_array[0]))
 #define SMALL_BUFFER_SIZE   512
 #define MED_BUFFER_SIZE     1024
 #define BIG_BUFFER_SIZE     2048
@@ -341,40 +341,40 @@ nsresult nsTestUConv::DisplayCharsets()
   }
 
 
   printf("***** Character Sets *****\n");
 
   PRUint32 encCount = 0, decCount = 0;
   PRUint32 basicEncCount = 0, basicDecCount = 0;
 
-  nsCStringArray allCharsets;
+  nsTArray<nsCString> allCharsets;
   
   nsCAutoString charset;
   PRBool hasMore;
   encoders->HasMore(&hasMore);
   while (hasMore) {
     res = encoders->GetNext(charset);
     if (NS_SUCCEEDED(res))
-      allCharsets.AppendCString(charset);
+      allCharsets.AppendElement(charset);
 
     encoders->HasMore(&hasMore);
   }
 
   nsAutoString prop, str;
-  PRUint32 count = allCharsets.Count();
+  PRUint32 count = allCharsets.Length();
   for (PRUint32 i = 0; i < count; i++) {
 
-    const nsCString* charset = allCharsets[i];
-    printf("%s", charset->get());
-    PrintSpaces(24 - charset->Length());  // align to hard coded column number
+    const nsCString& charset = allCharsets[i];
+    printf("%s", charset.get());
+    PrintSpaces(24 - charset.Length());  // align to hard coded column number
 
 
     nsCOMPtr<nsIUnicodeDecoder> dec = NULL;
-    res = ccMan->GetUnicodeDecoder(charset->get(), getter_AddRefs(dec));
+    res = ccMan->GetUnicodeDecoder(charset.get(), getter_AddRefs(dec));
     if (NS_FAILED(res)) printf (" "); 
     else {
       printf("D");
       decCount++;
     }
 #ifdef NS_DEBUG
     // show the "basic" decoder classes
     if (dec) {
@@ -384,17 +384,17 @@ nsresult nsTestUConv::DisplayCharsets()
         printf("b");
       }
       else printf(" ");
     }
     else printf(" ");
 #endif
 
     nsCOMPtr<nsIUnicodeEncoder> enc = NULL;
-    res = ccMan->GetUnicodeEncoder(charset->get(), getter_AddRefs(enc));
+    res = ccMan->GetUnicodeEncoder(charset.get(), getter_AddRefs(enc));
     if (NS_FAILED(res)) printf (" "); 
     else {
       printf("E");
       encCount++;
     }
 
 #ifdef NS_DEBUG
     if (enc) {
@@ -406,37 +406,37 @@ nsresult nsTestUConv::DisplayCharsets()
       else printf(" ");
     }
     else printf(" ");
 #endif
     
     printf(" ");
 
     prop.AssignLiteral(".notForBrowser");
-    res = ccMan->GetCharsetData(charset->get(), prop.get(), str);
+    res = ccMan->GetCharsetData(charset.get(), prop.get(), str);
     if ((dec != NULL) && (NS_FAILED(res))) printf ("B"); 
     else printf("X");
 
     prop.AssignLiteral(".notForComposer");
-    res = ccMan->GetCharsetData(charset->get(), prop.get(), str);
+    res = ccMan->GetCharsetData(charset.get(), prop.get(), str);
     if ((enc != NULL) && (NS_FAILED(res))) printf ("C"); 
     else printf("X");
 
     prop.AssignLiteral(".notForMailView");
-    res = ccMan->GetCharsetData(charset->get(), prop.get(), str);
+    res = ccMan->GetCharsetData(charset.get(), prop.get(), str);
     if ((dec != NULL) && (NS_FAILED(res))) printf ("V"); 
     else printf("X");
 
     prop.AssignLiteral(".notForMailEdit");
-    res = ccMan->GetCharsetData(charset->get(), prop.get(), str);
+    res = ccMan->GetCharsetData(charset.get(), prop.get(), str);
     if ((enc != NULL) && (NS_FAILED(res))) printf ("E"); 
     else printf("X");
 
     printf("(%3d, %3d) ", encCount, decCount);
-    res = ccMan->GetCharsetTitle(charset->get(), str);
+    res = ccMan->GetCharsetTitle(charset.get(), str);
     if (NS_FAILED(res)) str.SetLength(0);
     NS_LossyConvertUTF16toASCII buff2(str);
     printf(" \"%s\"\n", buff2.get());
   }
 
   printf("%u of %u decoders are basic (%d%%)\n",
          basicDecCount, decCount, (basicDecCount * 100) / decCount);
 
--- a/intl/unicharutil/src/nsSaveAsCharset.cpp
+++ b/intl/unicharutil/src/nsSaveAsCharset.cpp
@@ -41,16 +41,18 @@
 #include "prprf.h"
 #include "nsIServiceManager.h"
 #include "nsIComponentManager.h"
 #include "nsICharsetConverterManager.h"
 #include "nsSaveAsCharset.h"
 #include "nsCRT.h"
 #include "nsUnicharUtils.h"
 #include "nsCompressedCharMap.h"
+#include "nsReadableUtils.h"
+#include "nsWhitespaceTokenizer.h"
 
 //
 // nsISupports methods
 //
 NS_IMPL_ISUPPORTS1(nsSaveAsCharset, nsISaveAsCharset)
 
 //
 // nsSaveAsCharset
@@ -143,17 +145,17 @@ nsSaveAsCharset::Convert(const PRUnichar
 
 NS_IMETHODIMP 
 nsSaveAsCharset::GetCharset(char * *aCharset)
 {
   NS_ENSURE_ARG(aCharset);
   NS_ASSERTION(mCharsetListIndex >= 0, "need to call Init() first");
   NS_ENSURE_TRUE(mCharsetListIndex >= 0, NS_ERROR_FAILURE);
 
-  const char *charset = mCharsetList[mCharsetListIndex]->get();
+  const char* charset = mCharsetList[mCharsetListIndex].get();
   if (!charset) {
     *aCharset = nsnull;
     NS_ASSERTION(charset, "make sure to call Init() with non empty charset list");
     return NS_ERROR_FAILURE;
   }
 
   *aCharset = nsCRT::strdup(charset);
   return (*aCharset) ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
@@ -373,28 +375,31 @@ nsresult nsSaveAsCharset::SetupCharsetLi
   if (!charsetList[0])
     return NS_ERROR_INVALID_ARG;
 
   if (mCharsetListIndex >= 0) {
     mCharsetList.Clear();
     mCharsetListIndex = -1;
   }
 
-  mCharsetList.ParseString(charsetList, ", ");
+  nsCWhitespaceTokenizer tokenizer = nsDependentCString(charsetList);
+  while (tokenizer.hasMoreTokens()) {
+    ParseString(tokenizer.nextToken(), ',', mCharsetList);
+  }
 
   return NS_OK;
 }
 
 const char * nsSaveAsCharset::GetNextCharset()
 {
-  if ((mCharsetListIndex + 1) >= mCharsetList.Count())
+  if ((mCharsetListIndex + 1) >= PRInt32(mCharsetList.Length()))
     return nsnull;
 
   // bump the index and return the next charset
-  return mCharsetList[++mCharsetListIndex]->get();
+  return mCharsetList[++mCharsetListIndex].get();
 }
 
 /////////////////////////////////////////////////////////////////////////////////////////
 
 nsresult 
 NS_NewSaveAsCharset(nsISupports **inst)
 {
   if(nsnull == inst )
--- a/intl/unicharutil/src/nsSaveAsCharset.h
+++ b/intl/unicharutil/src/nsSaveAsCharset.h
@@ -32,17 +32,17 @@
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsIFactory.h"
 #include "nsString.h"
-#include "nsVoidArray.h"
+#include "nsTArray.h"
 #include "nsICharsetConverterManager.h"
 #include "nsISaveAsCharset.h"
 
 
 #define MASK_FALLBACK(a) (nsISaveAsCharset::mask_Fallback & (a))
 #define MASK_ENTITY(a) (nsISaveAsCharset::mask_Entity & (a))
 #define MASK_CHARSET_FALLBACK(a) (nsISaveAsCharset::mask_CharsetFallback & (a))
 #define ATTR_NO_FALLBACK(a) (nsISaveAsCharset::attr_FallbackNone == MASK_FALLBACK(a) && \
@@ -91,15 +91,15 @@ protected:
   nsresult SetupCharsetList(const char *charsetList);
 
   const char * GetNextCharset();
 
   PRUint32 mAttribute;                    // conversion attribute
   PRUint32 mEntityVersion;                // see nsIEntityConverter
   nsCOMPtr<nsIUnicodeEncoder> mEncoder;   // encoder (convert from unicode)
   nsCOMPtr<nsIEntityConverter> mEntityConverter;
-  nsCStringArray mCharsetList;
+  nsTArray<nsCString> mCharsetList;
   PRInt32        mCharsetListIndex;
 };
 
 
 nsresult NS_NewSaveAsCharset(nsISupports **inst);
 
--- a/modules/libjar/nsJARInputStream.cpp
+++ b/modules/libjar/nsJARInputStream.cpp
@@ -157,17 +157,17 @@ nsJARInputStream::InitDirectory(nsZipArc
     nsCAutoString pattern = escDirName + NS_LITERAL_CSTRING("?*~") +
                             escDirName + NS_LITERAL_CSTRING("?*/?*");
     rv = aZip->FindInit(pattern.get(), &find);
     if (NS_FAILED(rv)) return rv;
 
     const char *name;
     while ((rv = find->FindNext( &name )) == NS_OK) {
         // No need to copy string, just share the one from nsZipArchive
-        mArray.AppendCString(nsDependentCString(name));
+        mArray.AppendElement(nsDependentCString(name));
     }
     delete find;
 
     if (rv != NS_ERROR_FILE_TARGET_DOES_NOT_EXIST && NS_FAILED(rv)) {
         return NS_ERROR_FAILURE;    // no error translation
     }
 
     // Sort it
@@ -348,25 +348,25 @@ nsJARInputStream::ReadDirectory(char* aB
 
     // If the buffer contains data, copy what's there up to the desired amount
     PRUint32 numRead = CopyDataToBuffer(aBuffer, aCount);
 
     if (aCount > 0) {
         // empty the buffer and start writing directory entry lines to it
         mBuffer.Truncate();
         mCurPos = 0;
-        const PRUint32 arrayLen = mArray.Count();
+        const PRUint32 arrayLen = mArray.Length();
 
         for ( ;aCount > mBuffer.Length(); mArrPos++) {
             // have we consumed all the directory contents?
             if (arrayLen <= mArrPos)
                 break;
 
-            const char * entryName = mArray[mArrPos]->get();
-            PRUint32 entryNameLen = mArray[mArrPos]->Length();
+            const char * entryName = mArray[mArrPos].get();
+            PRUint32 entryNameLen = mArray[mArrPos].Length();
             nsZipItem* ze = mZip->GetItem(entryName);
             NS_ENSURE_TRUE(ze, NS_ERROR_FILE_TARGET_DOES_NOT_EXIST);
 
             // Last Modified Time
             PRExplodedTime tm;
             PR_ExplodeTime(GetModTime(ze->date, ze->time), PR_GMTParameters, &tm);
             char itemLastModTime[65];
             PR_FormatTimeUSEnglish(itemLastModTime,
--- a/modules/libjar/nsJARInputStream.h
+++ b/modules/libjar/nsJARInputStream.h
@@ -37,16 +37,17 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef nsJARINPUTSTREAM_h__
 #define nsJARINPUTSTREAM_h__
 
 #include "nsIInputStream.h"
 #include "nsJAR.h"
+#include "nsTArray.h"
 
 /*-------------------------------------------------------------------------
  * Class nsJARInputStream declaration. This class defines the type of the
  * object returned by calls to nsJAR::GetInputStream(filename) for the
  * purpose of reading a file item out of a JAR file. 
  *------------------------------------------------------------------------*/
 class nsJARInputStream : public nsIInputStream
 {
@@ -81,17 +82,17 @@ class nsJARInputStream : public nsIInput
     };
     struct InflateStruct *   mInflate;
 
     /* For directory reading */
     nsZipArchive*           mZip;        // the zipReader
     PRUint32                mNameLen; // length of dirname
     nsCAutoString           mBuffer;  // storage for generated text of stream
     PRUint32                mArrPos;  // current position within mArray
-    nsCStringArray          mArray;   // array of names in (zip) directory
+    nsTArray<nsCString>     mArray;   // array of names in (zip) directory
 
     PRPackedBool    mDirectory;
     PRPackedBool    mClosed;          // Whether the stream is closed
 
     nsresult ContinueInflate(char* aBuf, PRUint32 aCount, PRUint32* aBytesRead);
     nsresult ReadDirectory(char* aBuf, PRUint32 aCount, PRUint32* aBytesRead);
     PRUint32 CopyDataToBuffer(char* &aBuffer, PRUint32 &aCount);
 };
--- a/modules/libpref/src/nsPrefBranch.cpp
+++ b/modules/libpref/src/nsPrefBranch.cpp
@@ -652,17 +652,17 @@ NS_IMETHODIMP nsPrefBranch::AddObserver(
     nsCOMPtr<nsIWeakReference> tmp = do_GetWeakReference(weakRefFactory);
     NS_ADDREF(pCallback->pWeakRef = tmp);
   } else {
     pCallback->pWeakRef = nsnull;
     NS_ADDREF(pCallback->pObserver);
   }
 
   mObservers->AppendElement(pCallback);
-  mObserverDomains.AppendCString(nsCString(aDomain));
+  mObserverDomains.AppendElement(nsCString(aDomain));
 
   // We must pass a fully qualified preference name to the callback
   pref = getPrefName(aDomain); // aDomain == nsnull only possible failure, trapped above
   PREF_RegisterCallback(pref, NotifyObserver, pCallback);
   return NS_OK;
 }
 
 NS_IMETHODIMP nsPrefBranch::RemoveObserver(const char *aDomain, nsIObserver *aObserver)
@@ -684,26 +684,26 @@ NS_IMETHODIMP nsPrefBranch::RemoveObserv
   count = mObservers->Count();
   if (count == 0)
     return NS_OK;
 
   for (i = 0; i < count; i++) {
     pCallback = (PrefCallbackData *)mObservers->ElementAt(i);
     if (pCallback) {
       if (pCallback->pObserver == aObserver) {
-        mObserverDomains.CStringAt(i, domain);
+        domain = mObserverDomains[i];
         if (domain.Equals(aDomain)) {
           // We must pass a fully qualified preference name to remove the callback
           pref = getPrefName(aDomain); // aDomain == nsnull only possible failure, trapped above
           rv = PREF_UnregisterCallback(pref, NotifyObserver, pCallback);
           if (NS_SUCCEEDED(rv)) {
             // Remove this observer from our array so that nobody else can remove
             // what we're trying to remove ourselves right now.
             mObservers->RemoveElementAt(i);
-            mObserverDomains.RemoveCStringAt(i);
+            mObserverDomains.RemoveElementAt(i);
             if (pCallback->pWeakRef) {
               NS_RELEASE(pCallback->pWeakRef);
             } else {
               NS_RELEASE(pCallback->pObserver);
             }
             nsMemory::Free(pCallback);
           }
           return rv;
@@ -763,17 +763,17 @@ void nsPrefBranch::freeObserverList(void
 
     count = mObservers->Count();
     if (count > 0) {
       PRInt32 i;
       nsCAutoString domain;
       for (i = 0; i < count; ++i) {
         pCallback = (PrefCallbackData *)mObservers->ElementAt(i);
         if (pCallback) {
-          mObserverDomains.CStringAt(i, domain);
+          domain = mObserverDomains[i];
           // We must pass a fully qualified preference name to remove the callback
           pref = getPrefName(domain.get()); // can't fail because domain must be valid
           // Remove this observer from our array so that nobody else can remove
           // what we're trying to remove right now.
           mObservers->ReplaceElementAt(nsnull, i);
           PREF_UnregisterCallback(pref, NotifyObserver, pCallback);
           if (pCallback->pWeakRef) {
             NS_RELEASE(pCallback->pWeakRef);
--- a/modules/libpref/src/nsPrefBranch.h
+++ b/modules/libpref/src/nsPrefBranch.h
@@ -45,16 +45,17 @@
 #include "nsIPrefLocalizedString.h"
 #include "nsISecurityPref.h"
 #include "nsXPCOM.h"
 #include "nsISupportsPrimitives.h"
 #include "nsIRelativeFilePref.h"
 #include "nsILocalFile.h"
 #include "nsString.h"
 #include "nsVoidArray.h"
+#include "nsTArray.h"
 #include "nsWeakReference.h"
 
 class nsPrefBranch : public nsIPrefBranchInternal,
                      public nsISecurityPref,
                      public nsIObserver,
                      public nsSupportsWeakReference
 {
 public:
@@ -74,21 +75,21 @@ protected:
     { }
 
   nsresult   GetDefaultFromPropertiesFile(const char *aPrefName, PRUnichar **return_buf);
   const char *getPrefName(const char *aPrefName);
   nsresult   getValidatedPrefName(const char *aPrefName, const char **_retval);
   void       freeObserverList(void);
 
 private:
-  PRInt32         mPrefRootLength;
-  nsAutoVoidArray *mObservers;
-  nsCString       mPrefRoot;
-  nsCStringArray  mObserverDomains;
-  PRBool          mIsDefault;
+  PRInt32               mPrefRootLength;
+  nsAutoVoidArray       *mObservers;
+  nsCString             mPrefRoot;
+  nsTArray<nsCString>   mObserverDomains;
+  PRBool                mIsDefault;
 
 };
 
 
 class nsPrefLocalizedString : public nsIPrefLocalizedString,
                               public nsISupportsString
 {
 public:
--- a/netwerk/base/src/nsIOService.cpp
+++ b/netwerk/base/src/nsIOService.cpp
@@ -66,16 +66,17 @@
 #include "nsNetCID.h"
 #include "nsIRecyclingAllocator.h"
 #include "nsISocketTransport.h"
 #include "nsCRT.h"
 #include "nsINestedURI.h"
 #include "nsNetUtil.h"
 #include "nsThreadUtils.h"
 #include "nsIPermissionManager.h"
+#include "nsTArray.h"
 
 #if defined(XP_WIN)
 #include "nsNativeConnectionHelper.h"
 #endif
 
 #define PORT_PREF_PREFIX           "network.security.ports."
 #define PORT_PREF(x)               PORT_PREF_PREFIX x
 #define AUTODIAL_PREF              "network.autodial-helper.enabled"
@@ -743,36 +744,36 @@ nsIOService::PrefsChanged(nsIPrefBranch 
 void
 nsIOService::ParsePortList(nsIPrefBranch *prefBranch, const char *pref, PRBool remove)
 {
     nsXPIDLCString portList;
 
     // Get a pref string and chop it up into a list of ports.
     prefBranch->GetCharPref(pref, getter_Copies(portList));
     if (portList) {
-        nsCStringArray portListArray;
-        portListArray.ParseString(portList.get(), ",");
-        PRInt32 index;
-        for (index=0; index < portListArray.Count(); index++) {
-            portListArray[index]->StripWhitespace();
+        nsTArray<nsCString> portListArray;
+        ParseString(portList, ',', portListArray);
+        PRUint32 index;
+        for (index=0; index < portListArray.Length(); index++) {
+            portListArray[index].StripWhitespace();
             PRInt32 aErrorCode, portBegin, portEnd;
 
-            if (PR_sscanf(portListArray[index]->get(), "%d-%d", &portBegin, &portEnd) == 2) {
+            if (PR_sscanf(portListArray[index].get(), "%d-%d", &portBegin, &portEnd) == 2) {
                if ((portBegin < 65536) && (portEnd < 65536)) {
                    PRInt32 curPort;
                    if (remove) {
                         for (curPort=portBegin; curPort <= portEnd; curPort++)
                             mRestrictedPortList.RemoveElement((void*)curPort);
                    } else {
                         for (curPort=portBegin; curPort <= portEnd; curPort++)
                             mRestrictedPortList.AppendElement((void*)curPort);
                    }
                }
             } else {
-               PRInt32 port = portListArray[index]->ToInteger(&aErrorCode);
+               PRInt32 port = portListArray[index].ToInteger(&aErrorCode);
                if (NS_SUCCEEDED(aErrorCode) && port < 65536) {
                    if (remove)
                        mRestrictedPortList.RemoveElement((void*)port);
                    else
                        mRestrictedPortList.AppendElement((void*)port);
                }
             }
 
--- a/netwerk/base/src/nsURLHelperOSX.cpp
+++ b/netwerk/base/src/nsURLHelperOSX.cpp
@@ -38,49 +38,49 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 /* Mac OS X-specific local file uri parsing */
 #include "nsURLHelper.h"
 #include "nsEscape.h"
 #include "nsILocalFile.h"
-#include "nsVoidArray.h"
+#include "nsTArray.h"
 #include "nsReadableUtils.h"
 #include <Files.h>
 
-static nsCStringArray *gVolumeList = nsnull;
+static nsTArray<nsCString> *gVolumeList = nsnull;
 
 static PRBool pathBeginsWithVolName(const nsACString& path, nsACString& firstPathComponent)
 {
   // Return whether the 1st path component in path (escaped) is equal to the name
   // of a mounted volume. Return the 1st path component (unescaped) in any case.
   // This needs to be done as quickly as possible, so we cache a list of volume names.
   // XXX Register an event handler to detect drives being mounted/unmounted?
   
   if (!gVolumeList) {
-    gVolumeList = new nsCStringArray;
+    gVolumeList = new nsTArray<nsCString>;
     if (!gVolumeList) {
       return PR_FALSE; // out of memory
     }
   }
 
   // Cache a list of volume names
-  if (!gVolumeList->Count()) {
+  if (!gVolumeList->Length()) {
     OSErr err;
     ItemCount volumeIndex = 1;
     
     do {
       HFSUniStr255 volName;
       FSRef rootDirectory;
       err = ::FSGetVolumeInfo(0, volumeIndex, NULL, kFSVolInfoNone, NULL, &volName, &rootDirectory);
       if (err == noErr) {
         NS_ConvertUTF16toUTF8 volNameStr(Substring((PRUnichar *)volName.unicode,
                                                    (PRUnichar *)volName.unicode + volName.length));
-        gVolumeList->AppendCString(volNameStr);
+        gVolumeList->AppendElement(volNameStr);
         volumeIndex++;
       }
     } while (err == noErr);
   }
   
   // Extract the first component of the path
   nsACString::const_iterator start;
   path.BeginReading(start);
--- a/netwerk/streamconv/src/nsStreamConverterService.cpp
+++ b/netwerk/streamconv/src/nsStreamConverterService.cpp
@@ -303,17 +303,17 @@ public:
 };
 
 // walks the graph using a breadth-first-search algorithm which generates a discovered
 // verticies tree. This tree is then walked up (from destination vertex, to origin vertex)
 // and each link in the chain is added to an nsStringArray. A direct lookup for the given
 // CONTRACTID should be made prior to calling this method in an attempt to find a direct
 // converter rather than walking the graph.
 nsresult
-nsStreamConverterService::FindConverter(const char *aContractID, nsCStringArray **aEdgeList) {
+nsStreamConverterService::FindConverter(const char *aContractID, nsTArray<nsCString> **aEdgeList) {
     nsresult rv;
     if (!aEdgeList) return NS_ERROR_NULL_POINTER;
     *aEdgeList = nsnull;
 
     // walk the graph in search of the appropriate converter.
 
     PRInt32 vertexCount = mAdjacencyList->Count();
     if (0 >= vertexCount) return NS_ERROR_FAILURE;
@@ -415,17 +415,17 @@ nsStreamConverterService::FindConverter(
     // first parse out the FROM and TO MIME-types being registered.
 
     nsCAutoString fromStr, toStr;
     rv = ParseFromTo(aContractID, fromStr, toStr);
     if (NS_FAILED(rv)) return rv;
 
     // get the root CONTRACTID
     nsCAutoString ContractIDPrefix(NS_ISTREAMCONVERTER_KEY);
-    nsCStringArray *shortestPath = new nsCStringArray();
+    nsTArray<nsCString> *shortestPath = new nsTArray<nsCString>();
     if (!shortestPath) return NS_ERROR_OUT_OF_MEMORY;
 
     nsCStringKey toMIMEType(toStr);
     data = (SCTableData*)lBFSTable.Get(&toMIMEType);
     if (!data) {
         // If this vertex isn't in the BFSTable, then no-one has registered for it,
         // therefore we can't do the conversion.
         delete shortestPath;
@@ -456,17 +456,17 @@ nsStreamConverterService::FindConverter(
 
         nsCStringKey *predecessorKey = predecessorData->key;
         newContractID.Append(predecessorKey->GetString());
 
         newContractID.AppendLiteral("&to=");
         newContractID.Append(key->GetString());
     
         // Add this CONTRACTID to the chain.
-        rv = shortestPath->AppendCString(newContractID) ? NS_OK : NS_ERROR_FAILURE;  // XXX this method incorrectly returns a bool
+        rv = shortestPath->AppendElement(newContractID) ? NS_OK : NS_ERROR_FAILURE;  // XXX this method incorrectly returns a bool
         NS_ASSERTION(NS_SUCCEEDED(rv), "AppendElement failed");
 
         // move up the tree.
         data = predecessorData;
     }
     delete shortestPath;
     return NS_ERROR_FAILURE; // couldn't find a stream converter or chain.
 }
@@ -496,17 +496,17 @@ nsStreamConverterService::CanConvert(con
     if (*_retval)
         return NS_OK;
 
     // Otherwise try the graph.
     rv = BuildGraph();
     if (NS_FAILED(rv))
         return rv;
 
-    nsCStringArray *converterChain = nsnull;
+    nsTArray<nsCString> *converterChain = nsnull;
     rv = FindConverter(contractID.get(), &converterChain);
     *_retval = NS_SUCCEEDED(rv);
 
     delete converterChain;
     return NS_OK;
 }
 
 NS_IMETHODIMP
@@ -528,41 +528,36 @@ nsStreamConverterService::Convert(nsIInp
     const char *cContractID = contractID.get();
 
     nsCOMPtr<nsIStreamConverter> converter(do_CreateInstance(cContractID, &rv));
     if (NS_FAILED(rv)) {
         // couldn't go direct, let's try walking the graph of converters.
         rv = BuildGraph();
         if (NS_FAILED(rv)) return rv;
 
-        nsCStringArray *converterChain = nsnull;
+        nsTArray<nsCString> *converterChain = nsnull;
 
         rv = FindConverter(cContractID, &converterChain);
         if (NS_FAILED(rv)) {
             // can't make this conversion.
             // XXX should have a more descriptive error code.
             return NS_ERROR_FAILURE;
         }
 
-        PRInt32 edgeCount = converterChain->Count();
+        PRInt32 edgeCount = PRInt32(converterChain->Length());
         NS_ASSERTION(edgeCount > 0, "findConverter should have failed");
 
 
         // convert the stream using each edge of the graph as a step.
         // this is our stream conversion traversal.
         nsCOMPtr<nsIInputStream> dataToConvert = aFromStream;
         nsCOMPtr<nsIInputStream> convertedData;
 
         for (PRInt32 i = edgeCount-1; i >= 0; i--) {
-            nsCString *contractIDStr = converterChain->CStringAt(i);
-            if (!contractIDStr) {
-                delete converterChain;
-                return NS_ERROR_FAILURE;
-            }
-            const char *lContractID = contractIDStr->get();
+            const char *lContractID = converterChain->ElementAt(i).get();
 
             converter = do_CreateInstance(lContractID, &rv);
 
             if (NS_FAILED(rv)) {
                 delete converterChain;                
                 return rv;
             }
 
@@ -614,42 +609,37 @@ nsStreamConverterService::AsyncConvertDa
     const char *cContractID = contractID.get();
 
     nsCOMPtr<nsIStreamConverter> listener(do_CreateInstance(cContractID, &rv));
     if (NS_FAILED(rv)) {
         // couldn't go direct, let's try walking the graph of converters.
         rv = BuildGraph();
         if (NS_FAILED(rv)) return rv;
 
-        nsCStringArray *converterChain = nsnull;
+        nsTArray<nsCString> *converterChain = nsnull;
 
         rv = FindConverter(cContractID, &converterChain);
         if (NS_FAILED(rv)) {
             // can't make this conversion.
             // XXX should have a more descriptive error code.
             return NS_ERROR_FAILURE;
         }
 
         // aListener is the listener that wants the final, converted, data.
         // we initialize finalListener w/ aListener so it gets put at the 
         // tail end of the chain, which in the loop below, means the *first*
         // converter created.
         nsCOMPtr<nsIStreamListener> finalListener = aListener;
 
         // convert the stream using each edge of the graph as a step.
         // this is our stream conversion traversal.
-        PRInt32 edgeCount = converterChain->Count();
+        PRInt32 edgeCount = PRInt32(converterChain->Length());
         NS_ASSERTION(edgeCount > 0, "findConverter should have failed");
         for (int i = 0; i < edgeCount; i++) {
-            nsCString *contractIDStr = converterChain->CStringAt(i);
-            if (!contractIDStr) {
-                delete converterChain;
-                return NS_ERROR_FAILURE;
-            }
-            const char *lContractID = contractIDStr->get();
+            const char *lContractID = converterChain->ElementAt(i).get();
 
             // create the converter for this from/to pair
             nsCOMPtr<nsIStreamConverter> converter(do_CreateInstance(lContractID));
             NS_ASSERTION(converter, "graph construction problem, built a contractid that wasn't registered");
 
             nsCAutoString fromStr, toStr;
             rv = ParseFromTo(lContractID, fromStr, toStr);
             if (NS_FAILED(rv)) {
--- a/netwerk/streamconv/src/nsStreamConverterService.h
+++ b/netwerk/streamconv/src/nsStreamConverterService.h
@@ -37,16 +37,17 @@
 
 #ifndef __nsstreamconverterservice__h___
 #define __nsstreamconverterservice__h___
 
 #include "nsIStreamConverterService.h"
 #include "nsIStreamListener.h"
 #include "nsHashtable.h"
 #include "nsCOMArray.h"
+#include "nsTArray.h"
 #include "nsIAtom.h"
 
 class nsStreamConverterService : public nsIStreamConverterService {
 public:    
     /////////////////////////////////////////////////////
     // nsISupports methods
     NS_DECL_ISUPPORTS
 
@@ -60,17 +61,17 @@ public:
     nsStreamConverterService();
     virtual ~nsStreamConverterService();
 
     // Initialization routine. Must be called after this object is constructed.
     nsresult Init();
 
 private:
     // Responsible for finding a converter for the given MIME-type.
-    nsresult FindConverter(const char *aContractID, nsCStringArray **aEdgeList);
+    nsresult FindConverter(const char *aContractID, nsTArray<nsCString> **aEdgeList);
     nsresult BuildGraph(void);
     nsresult AddAdjacency(const char *aContractID);
     nsresult ParseFromTo(const char *aContractID, nsCString &aFromRes, nsCString &aToRes);
 
     // member variables
     nsObjectHashtable              *mAdjacencyList;
 };
 
--- a/storage/src/mozStorageStatement.cpp
+++ b/storage/src/mozStorageStatement.cpp
@@ -217,17 +217,17 @@ mozStorageStatement::Initialize(mozStora
 
     mDBConnection = aDBConnection;
     mParamCount = sqlite3_bind_parameter_count (mDBStatement);
     mResultColumnCount = sqlite3_column_count (mDBStatement);
     mColumnNames.Clear();
 
     for (PRUint32 i = 0; i < mResultColumnCount; i++) {
         const char *name = sqlite3_column_name(mDBStatement, i);
-        mColumnNames.AppendCString(nsDependentCString(name));
+        mColumnNames.AppendElement(nsDependentCString(name));
     }
 
 #ifdef DEBUG
     // We want to try and test for LIKE and that consumers are using
     // escapeStringForLIKE instead of just trusting user input.  The idea to
     // check to see if they are binding a parameter after like instead of just
     // using a string.  We only do this in debug builds because it's expensive!
     const nsCaseInsensitiveCStringComparator c;
@@ -423,17 +423,17 @@ NS_IMETHODIMP
 mozStorageStatement::GetColumnIndex(const nsACString &aName, PRUint32 *_retval)
 {
     if (!mDBConnection || !mDBStatement)
         return NS_ERROR_NOT_INITIALIZED;
 
     // Surprisingly enough, SQLite doesn't provide an API for this.  We have to
     // determine it ourselves sadly.
     for (PRUint32 i = 0; i < mResultColumnCount; i++) {
-        if (mColumnNames[i]->Equals(aName)) {
+        if (mColumnNames[i].Equals(aName)) {
             *_retval = i;
             return NS_OK;
         }
     }
 
     return NS_ERROR_INVALID_ARG;
 }
 
--- a/storage/src/mozStorageStatement.h
+++ b/storage/src/mozStorageStatement.h
@@ -37,17 +37,17 @@
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef _MOZSTORAGESTATEMENT_H_
 #define _MOZSTORAGESTATEMENT_H_
 
 #include "nsAutoPtr.h"
 #include "nsString.h"
 
-#include "nsVoidArray.h"
+#include "nsTArray.h"
 
 #include "mozIStorageStatement.h"
 
 #include <sqlite3.h>
 
 class mozStorageConnection;
 class nsIXPConnectJSObjectHolder;
 class mozStorageStatementJSHelper;
@@ -83,17 +83,17 @@ public:
 private:
     ~mozStorageStatement();
 
 protected:
     nsRefPtr<mozStorageConnection> mDBConnection;
     sqlite3_stmt *mDBStatement;
     PRUint32 mParamCount;
     PRUint32 mResultColumnCount;
-    nsCStringArray mColumnNames;
+    nsTArray<nsCString> mColumnNames;
     PRBool mExecuting;
 
     /**
      * The following two members are only used with the JS helper.  They cache
      * the row and params objects.
      */
     nsCOMPtr<nsIXPConnectJSObjectHolder> mStatementParamsHolder;
     nsCOMPtr<nsIXPConnectJSObjectHolder> mStatementRowHolder;
--- a/toolkit/components/url-classifier/src/nsUrlClassifierDBService.cpp
+++ b/toolkit/components/url-classifier/src/nsUrlClassifierDBService.cpp
@@ -60,18 +60,18 @@
 #include "nsIProperties.h"
 #include "nsIProxyObjectManager.h"
 #include "nsToolkitCompsCID.h"
 #include "nsIUrlClassifierUtils.h"
 #include "nsUrlClassifierDBService.h"
 #include "nsUrlClassifierUtils.h"
 #include "nsURILoader.h"
 #include "nsString.h"
+#include "nsReadableUtils.h"
 #include "nsTArray.h"
-#include "nsVoidArray.h"
 #include "nsNetUtil.h"
 #include "nsNetCID.h"
 #include "nsThreadUtils.h"
 #include "nsXPCOMStrings.h"
 #include "prlog.h"
 #include "prlock.h"
 #include "prprf.h"
 #include "prnetdb.h"
@@ -1459,28 +1459,28 @@ nsUrlClassifierDBServiceWorker::GetLooku
    * From the protocol doc:
    * For the hostname, the client will try at most 5 different strings.  They
    * are:
    * a) The exact hostname of the url
    * b) The 4 hostnames formed by starting with the last 5 components and
    *    successivly removing the leading component.  The top-level component
    *    can be skipped.
    */
-  nsCStringArray hosts;
-  hosts.AppendCString(host);
+  nsTArray<nsCString> hosts;
+  hosts.AppendElement(host);
 
   host.BeginReading(begin);
   host.EndReading(end);
   int numComponents = 0;
   while (RFindInReadable(NS_LITERAL_CSTRING("."), begin, end) &&
          numComponents < MAX_HOST_COMPONENTS) {
     // don't bother checking toplevel domains
     if (++numComponents >= 2) {
       host.EndReading(iter);
-      hosts.AppendCString(Substring(end, iter));
+      hosts.AppendElement(Substring(end, iter));
     }
     end = begin;
     host.BeginReading(begin);
   }
 
   /**
    * From the protocol doc:
    * For the path, the client will also try at most 6 different strings.
@@ -1488,47 +1488,47 @@ nsUrlClassifierDBServiceWorker::GetLooku
    * a) the exact path of the url, including query parameters
    * b) the exact path of the url, without query parameters
    * c) the 4 paths formed by starting at the root (/) and
    *    successively appending path components, including a trailing
    *    slash.  This behavior should only extend up to the next-to-last
    *    path component, that is, a trailing slash should never be
    *    appended that was not present in the original url.
    */
-  nsCStringArray paths;
-  paths.AppendCString(path);
+  nsTArray<nsCString> paths;
+  paths.AppendElement(path);
 
   path.BeginReading(iter);
   path.EndReading(end);
   if (FindCharInReadable('?', iter, end)) {
     path.BeginReading(begin);
     path = Substring(begin, iter);
-    paths.AppendCString(path);
+    paths.AppendElement(path);
   }
 
   // Check an empty path (for whole-domain blacklist entries)
-  paths.AppendCString(EmptyCString());
+  paths.AppendElement(EmptyCString());
 
   numComponents = 1;
   path.BeginReading(begin);
   path.EndReading(end);
   iter = begin;
   while (FindCharInReadable('/', iter, end) &&
          numComponents < MAX_PATH_COMPONENTS) {
     iter++;
-    paths.AppendCString(Substring(begin, iter));
+    paths.AppendElement(Substring(begin, iter));
     numComponents++;
   }
 
-  for (int hostIndex = 0; hostIndex < hosts.Count(); hostIndex++) {
-    for (int pathIndex = 0; pathIndex < paths.Count(); pathIndex++) {
+  for (PRUint32 hostIndex = 0; hostIndex < hosts.Length(); hostIndex++) {
+    for (PRUint32 pathIndex = 0; pathIndex < paths.Length(); pathIndex++) {
       nsCString key;
-      key.Assign(*hosts[hostIndex]);
+      key.Assign(hosts[hostIndex]);
       key.Append('/');
-      key.Append(*paths[pathIndex]);
+      key.Append(paths[pathIndex]);
       LOG(("Chking %s", key.get()));
 
       fragments.AppendElement(key);
     }
   }
 
   return NS_OK;
 }
@@ -2011,33 +2011,33 @@ nsUrlClassifierDBServiceWorker::GetKey(c
 
   if (IsCanonicalizedIP(host)) {
     nsCAutoString key;
     key.Assign(host);
     key.Append("/");
     return hash.FromPlaintext(key, mCryptoHash);
   }
 
-  nsCStringArray hostComponents;
-  hostComponents.ParseString(PromiseFlatCString(host).get(), ".");
-
-  if (hostComponents.Count() < 2)
+  nsTArray<nsCString> hostComponents;
+  ParseString(PromiseFlatCString(host), '.', hostComponents);
+
+  if (hostComponents.Length() < 2)
     return NS_ERROR_FAILURE;
 
-  PRInt32 last = hostComponents.Count() - 1;
+  PRInt32 last = PRInt32(hostComponents.Length()) - 1;
   nsCAutoString lookupHost;
 
-  if (hostComponents.Count() > 2) {
-    lookupHost.Append(*hostComponents[last - 2]);
+  if (hostComponents.Length() > 2) {
+    lookupHost.Append(hostComponents[last - 2]);
     lookupHost.Append(".");
   }
 
-  lookupHost.Append(*hostComponents[last - 1]);
+  lookupHost.Append(hostComponents[last - 1]);
   lookupHost.Append(".");
-  lookupHost.Append(*hostComponents[last]);
+  lookupHost.Append(hostComponents[last]);
   lookupHost.Append("/");
 
   return hash.FromPlaintext(lookupHost, mCryptoHash);
 }
 
 nsresult
 nsUrlClassifierDBServiceWorker::GetHostKeys(const nsACString &spec,
                                             nsTArray<nsCString> &hostKeys)
@@ -2058,41 +2058,41 @@ nsUrlClassifierDBServiceWorker::GetHostK
     if (!key)
       return NS_ERROR_OUT_OF_MEMORY;
 
     key->Assign(host);
     key->Append("/");
     return NS_OK;
   }
 
-  nsCStringArray hostComponents;
-  hostComponents.ParseString(PromiseFlatCString(host).get(), ".");
-
-  if (hostComponents.Count() < 2) {
+  nsTArray<nsCString> hostComponents;
+  ParseString(PromiseFlatCString(host), '.', hostComponents);
+
+  if (hostComponents.Length() < 2) {
     // no host or toplevel host, this won't match anything in the db
     return NS_OK;
   }
 
   // First check with two domain components
-  PRInt32 last = hostComponents.Count() - 1;
+  PRInt32 last = PRInt32(hostComponents.Length()) - 1;
   nsCString *lookupHost = hostKeys.AppendElement();
   if (!lookupHost)
     return NS_ERROR_OUT_OF_MEMORY;
 
-  lookupHost->Assign(*hostComponents[last - 1]);
+  lookupHost->Assign(hostComponents[last - 1]);
   lookupHost->Append(".");
-  lookupHost->Append(*hostComponents[last]);
+  lookupHost->Append(hostComponents[last]);
   lookupHost->Append("/");
 
   // Now check with three domain components
-  if (hostComponents.Count() > 2) {
+  if (hostComponents.Length() > 2) {
     nsCString *lookupHost2 = hostKeys.AppendElement();
     if (!lookupHost2)
       return NS_ERROR_OUT_OF_MEMORY;
-    lookupHost2->Assign(*hostComponents[last - 2]);
+    lookupHost2->Assign(hostComponents[last - 2]);
     lookupHost2->Append(".");
     lookupHost2->Append(*lookupHost);
   }
 
   return NS_OK;
 }
 
 nsresult
@@ -2212,40 +2212,40 @@ nsUrlClassifierDBServiceWorker::GetChunk
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   if (StringEndsWith(table, NS_LITERAL_CSTRING("-shavar"))) {
     rv = GetShaEntries(tableId, chunkType, chunkNum, DOMAIN_LENGTH, hashSize,
                        chunk, entries);
     NS_ENSURE_SUCCESS(rv, rv);
   } else {
-    nsCStringArray lines;
-    lines.ParseString(PromiseFlatCString(chunk).get(), "\n");
+    nsTArray<nsCString> lines;
+    ParseString(PromiseFlatCString(chunk), '\n', lines);
 
     // non-hashed tables need to be hashed
-    for (PRInt32 i = 0; i < lines.Count(); i++) {
+    for (PRInt32 i = 0; i < PRInt32(lines.Length()); i++) {
       nsUrlClassifierEntry *entry = entries.AppendElement();
       if (!entry)
         return NS_ERROR_OUT_OF_MEMORY;
 
       nsCAutoString entryStr;
       if (chunkType == CHUNK_SUB) {
         nsCString::const_iterator begin, iter, end;
-        lines[i]->BeginReading(begin);
-        lines[i]->EndReading(end);
+        lines[i].BeginReading(begin);
+        lines[i].EndReading(end);
         iter = begin;
         if (!FindCharInReadable(':', iter, end) ||
-            PR_sscanf(lines[i]->get(), "%d:", &entry->mAddChunkId) != 1) {
+            PR_sscanf(lines[i].get(), "%d:", &entry->mAddChunkId) != 1) {
           NS_WARNING("Received sub chunk without associated add chunk.");
           return NS_ERROR_FAILURE;
         }
         iter++;
         entryStr = Substring(iter, end);
       } else {
-        entryStr = *lines[i];
+        entryStr = lines[i];
       }
 
       rv = GetKey(entryStr, entry->mKey);
       NS_ENSURE_SUCCESS(rv, rv);
 
       entry->mTableId = tableId;
       entry->mChunkId = chunkNum;
       if (hashSize == PARTIAL_LENGTH) {
--- a/toolkit/components/url-classifier/src/nsUrlClassifierUtils.cpp
+++ b/toolkit/components/url-classifier/src/nsUrlClassifierUtils.cpp
@@ -34,17 +34,18 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsEscape.h"
 #include "nsString.h"
 #include "nsIURI.h"
 #include "nsNetUtil.h"
 #include "nsUrlClassifierUtils.h"
-#include "nsVoidArray.h"
+#include "nsTArray.h"
+#include "nsReadableUtils.h"
 #include "plbase64.h"
 #include "prmem.h"
 #include "prprf.h"
 
 static char int_to_hex_digit(PRInt32 i)
 {
   NS_ASSERTION((i >= 0) && (i <= 15), "int too big in int_to_hex_digit");
   return static_cast<char>(((i < 10) ? (i + '0') : ((i - 10) + 'A')));
@@ -258,49 +259,51 @@ nsUrlClassifierUtils::ParseIPAddress(con
   for (host.BeginReading(iter); iter != end; iter++) {
     if (!(isxdigit(*iter) || *iter == 'x' || *iter == 'X' || *iter == '.')) {
       // not an IP
       return;
     }
   }
 
   host.BeginReading(iter);
-  nsCStringArray parts;
-  parts.ParseString(PromiseFlatCString(Substring(iter, end)).get(), ".");
-  if (parts.Count() > 4) {
+  nsTArray<nsCString> parts;
+  ParseString(PromiseFlatCString(Substring(iter, end)), '.', parts);
+  if (parts.Length() > 4) {
     return;
   }
 
   // If any potentially-octal numbers (start with 0 but not hex) have
   // non-octal digits, no part of the ip can be in octal
   // XXX: this came from the old javascript implementation, is it really
   // supposed to be like this?
   PRBool allowOctal = PR_TRUE;
-  for (PRInt32 i = 0; i < parts.Count(); i++) {
-    const nsCString& part = *parts[i];
+  PRUint32 i;
+
+  for (i = 0; i < parts.Length(); i++) {
+    const nsCString& part = parts[i];
     if (part[0] == '0') {
       for (PRUint32 j = 1; j < part.Length(); j++) {
         if (part[j] == 'x') {
           break;
         }
         if (part[j] == '8' || part[j] == '9') {
           allowOctal = PR_FALSE;
           break;
         }
       }
     }
   }
 
-  for (PRInt32 i = 0; i < parts.Count(); i++) {
+  for (i = 0; i < parts.Length(); i++) {
     nsCAutoString canonical;
 
-    if (i == parts.Count() - 1) {
-      CanonicalNum(*parts[i], 5 - parts.Count(), allowOctal, canonical);
+    if (i == parts.Length() - 1) {
+      CanonicalNum(parts[i], 5 - parts.Length(), allowOctal, canonical);
     } else {
-      CanonicalNum(*parts[i], 1, allowOctal, canonical);
+      CanonicalNum(parts[i], 1, allowOctal, canonical);
     }
 
     if (canonical.IsEmpty()) {
       _retval.Truncate();
       return;
     }
 
     if (_retval.IsEmpty()) {
--- a/tools/trace-malloc/types.dat
+++ b/tools/trace-malloc/types.dat
@@ -577,17 +577,17 @@ MapToCCMap(unsigned int *)
 MapperToCCMap(nsICharRepresentable *)
 nsFontMetricsGTK::GetFontHandle(void *&)
 
 <nsFontMetricsGTK>
 PR_Malloc
 nsVoidArray::SizeTo(int)
 nsVoidArray::GrowArrayBy(int)
 nsVoidArray::InsertElementAt(void *, int)
-nsCStringArray::InsertCStringAt(nsCString const &, int)
+nsTArray<nsCString>::InsertElementAt(int, nsCString const &)
 nsFontMetricsGTK::QueryInterface(nsID const &, void **)
 
 <nsFontMetricsGTK>
 __builtin_new
 nsCStringKey::Clone(void) const
 nsHashtable::Put(nsHashKey *, void *)
 nsFontMetricsGTK::SearchNode(nsFontNode *, unsigned short)
 
@@ -2461,17 +2461,17 @@ nsCStringKey::Clone(void) const
 nsHashtable::Put(nsHashKey *, void *)
 nsExternalHelperAppService::AddMimeInfoToCache(nsIMIMEInfo *)
 
 <nsExternalHelperAppService>
 PR_Malloc
 nsVoidArray::SizeTo(int)
 nsVoidArray::GrowArrayBy(int)
 nsVoidArray::InsertElementAt(void *, int)
-nsCStringArray::InsertCStringAt(nsCString const &, int)
+nsTArray<nsCString>::InsertElementAt(int, nsCString const &)
 nsMIMEInfoImpl::SetFileExtensions(char const *)
 nsExternalHelperAppService::AddDefaultMimeTypesToCache(void)
  
 # ----------------------------------------------------------------------
 #
 # nsCategoryManager
 #
 
@@ -3626,17 +3626,17 @@ nsMemoryImpl::Alloc(unsigned int)
 nsMemory::Alloc(unsigned int)
 nsStr::Alloc(nsStr &, unsigned int)
 nsStr::Realloc(nsStr &, unsigned int)
 nsStr::EnsureCapacity(nsStr &, unsigned int)
 nsStr::GrowCapacity(nsStr &, unsigned int)
 nsStr::StrAppend(nsStr &, nsStr const &, unsigned int, int)
 nsStr::StrAssign(nsStr &, nsStr const &, unsigned int, int)
 nsCString::nsCString(nsCString const &)
-nsCStringArray::InsertCStringAt(nsCString const &, int)
+nsTArray<nsCString>::InsertElementAt(int, nsCString const &)
 nsPrefBranch::AddObserver(char const *, nsIObserver *)
 
 #----------------------------------------------------------------------
 
 <nsThread>
 PR_Calloc
 PR_SetThreadPrivate
 nsThread::RegisterThreadSelf(void)
@@ -5817,17 +5817,17 @@ PL_HashTableRawAdd
 nsHashtable::Put(nsHashKey *, void *)
 nsXMLMIMEDataSource::AddMapping(char const *, char const *, char const *, nsIURI *, unsigned int, unsigned int)
 
 <nsXMLMIMEDataSource>
 PR_Malloc
 nsVoidArray::SizeTo(int)
 nsVoidArray::GrowArrayBy(int)
 nsVoidArray::InsertElementAt(void *, int)
-nsCStringArray::InsertCStringAt(nsCString const &, int)
+nsTArray<nsCString>::InsertElementAt(int, nsCString const &)
 nsXMLMIMEDataSource::AddMapping(char const *, char const *, char const *, nsIURI *, unsigned int, unsigned int)
 
 <nsXMLMIMEDataSource>
 __builtin_new
 __builtin_vec_new
 nsSupportsArray::GrowArrayBy(int)
 nsSupportsArray::InsertElementAt(nsISupports *, unsigned int)
 nsSupportsArray::AppendElement(nsISupports *)
--- a/uriloader/exthandler/nsMIMEInfoImpl.cpp
+++ b/uriloader/exthandler/nsMIMEInfoImpl.cpp
@@ -107,68 +107,68 @@ nsMIMEInfoBase::GetFileExtensions(nsIUTF
   return NS_NewUTF8StringEnumerator(aResult, &mExtensions, this);
 }
 
 NS_IMETHODIMP
 nsMIMEInfoBase::ExtensionExists(const nsACString& aExtension, PRBool *_retval)
 {
     NS_ASSERTION(!aExtension.IsEmpty(), "no extension");
     PRBool found = PR_FALSE;
-    PRUint32 extCount = mExtensions.Count();
+    PRUint32 extCount = mExtensions.Length();
     if (extCount < 1) return NS_OK;
 
     for (PRUint8 i=0; i < extCount; i++) {
-        nsCString* ext = (nsCString*)mExtensions.CStringAt(i);
-        if (ext->Equals(aExtension, nsCaseInsensitiveCStringComparator())) {
+        const nsCString& ext = mExtensions[i];
+        if (ext.Equals(aExtension, nsCaseInsensitiveCStringComparator())) {
             found = PR_TRUE;
             break;
         }
     }
 
     *_retval = found;
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsMIMEInfoBase::GetPrimaryExtension(nsACString& _retval)
 {
-    PRUint32 extCount = mExtensions.Count();
-    if (extCount < 1) return NS_ERROR_NOT_INITIALIZED;
+    if (!mExtensions.Length())
+      return NS_ERROR_NOT_INITIALIZED;
 
-    _retval = *(mExtensions.CStringAt(0));
+    _retval = mExtensions[0];
     return NS_OK;    
 }
 
 NS_IMETHODIMP
 nsMIMEInfoBase::SetPrimaryExtension(const nsACString& aExtension)
 {
   NS_ASSERTION(!aExtension.IsEmpty(), "no extension");
-  PRUint32 extCount = mExtensions.Count();
+  PRUint32 extCount = mExtensions.Length();
   PRUint8 i;
   PRBool found = PR_FALSE;
   for (i=0; i < extCount; i++) {
-    nsCString* ext = (nsCString*)mExtensions.CStringAt(i);
-    if (ext->Equals(aExtension, nsCaseInsensitiveCStringComparator())) {
+    const nsCString& ext = mExtensions[i];
+    if (ext.Equals(aExtension, nsCaseInsensitiveCStringComparator())) {
       found = PR_TRUE;
       break;
     }
   }
   if (found) {
-    mExtensions.RemoveCStringAt(i);
+    mExtensions.RemoveElementAt(i);
   }
 
-  mExtensions.InsertCStringAt(aExtension, 0);
+  mExtensions.InsertElementAt(0, aExtension);
   
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsMIMEInfoBase::AppendExtension(const nsACString& aExtension)
 {
-  mExtensions.AppendCString(aExtension);
+  mExtensions.AppendElement(aExtension);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsMIMEInfoBase::GetType(nsACString& aType)
 {
     if (mType.IsEmpty())
         return NS_ERROR_NOT_INITIALIZED;
@@ -255,21 +255,21 @@ NS_IMETHODIMP
 nsMIMEInfoBase::SetFileExtensions(const nsACString& aExtensions)
 {
     mExtensions.Clear();
     nsCString extList( aExtensions );
     
     PRInt32 breakLocation = -1;
     while ( (breakLocation= extList.FindChar(',') )!= -1)
     {
-        mExtensions.AppendCString(Substring(extList.get(), extList.get() + breakLocation));
+        mExtensions.AppendElement(Substring(extList.get(), extList.get() + breakLocation));
         extList.Cut(0, breakLocation+1 );
     }
     if ( !extList.IsEmpty() )
-        mExtensions.AppendCString( extList );
+        mExtensions.AppendElement( extList );
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsMIMEInfoBase::GetDefaultDescription(nsAString& aDefaultDescription)
 {
   aDefaultDescription = mDefaultAppDescription;
   return NS_OK;
--- a/uriloader/exthandler/nsMIMEInfoImpl.h
+++ b/uriloader/exthandler/nsMIMEInfoImpl.h
@@ -37,17 +37,17 @@
  *
  * ***** END LICENSE BLOCK ***** */
 #ifndef __nsmimeinfoimpl_h___
 #define __nsmimeinfoimpl_h___
 
 #include "nsIMIMEInfo.h"
 #include "nsIAtom.h"
 #include "nsString.h"
-#include "nsVoidArray.h"
+#include "nsTArray.h"
 #include "nsIMutableArray.h"
 #include "nsIFile.h"
 #include "nsCOMPtr.h"
 #include "nsIURI.h"
 
 /** 
  * UTF8 moz-icon URI string for the default handler application's icon, if 
  * available.
@@ -120,17 +120,17 @@ class nsMIMEInfoBase : public nsIMIMEInf
      * function also ensures that aOther's primary extension will be the same as
      * the one of this object.
      */
     void CopyBasicDataTo(nsMIMEInfoBase* aOther);
 
     /**
      * Return whether this MIMEInfo has any extensions
      */
-    PRBool HasExtensions() const { return mExtensions.Count() != 0; }
+    PRBool HasExtensions() const { return mExtensions.Length() != 0; }
 
   protected:
     /**
      * Launch the default application for the given file.
      * For even more control over the launching, override launchWithFile.
      * Also see the comment about nsIMIMEInfo in general, above.
      *
      * @param aFile The file that should be opened
@@ -161,17 +161,17 @@ class nsMIMEInfoBase : public nsIMIMEInf
      *
      * @param  aURI      the file: URI in question
      * @param  aFile     the associated nsILocalFile (out param)
      */
     static NS_HIDDEN_(nsresult) GetLocalFileFromURI(nsIURI *aURI,
                                                     nsILocalFile **aFile);
 
     // member variables
-    nsCStringArray         mExtensions; ///< array of file extensions associated w/ this MIME obj
+    nsTArray<nsCString>    mExtensions; ///< array of file extensions associated w/ this MIME obj
     nsString               mDescription; ///< human readable description
     PRUint32               mMacType, mMacCreator; ///< Mac file type and creator
     nsCString              mType;
     HandlerClass           mClass;
     nsCOMPtr<nsIHandlerApp> mPreferredApplication;
     nsCOMPtr<nsIMutableArray> mPossibleApplications;
     nsHandlerInfoAction    mPreferredAction; ///< preferred action to associate with this type
     nsString               mPreferredAppDescription;
--- a/widget/src/gtk2/nsDeviceContextSpecG.cpp
+++ b/widget/src/gtk2/nsDeviceContextSpecG.cpp
@@ -1064,28 +1064,16 @@ NS_IMETHODIMP nsPrinterEnumeratorGTK::In
   return NS_ERROR_UNEXPECTED;
 }
 
 NS_IMETHODIMP nsPrinterEnumeratorGTK::DisplayPropertiesDlg(const PRUnichar *aPrinter, nsIPrintSettings *aPrintSettings)
 {
   return NS_OK;
 }
 
-
-//----------------------------------------------------------------------
-//String array enumeration callback to append a printer to the global
-//printer list.
-static PRBool
-GlobalPrinterEnumFunc(nsCString& aName, void *aData)
-{
-  nsTArray<nsString> *a = (nsTArray<nsString> *)aData;
-  a->AppendElement(NS_ConvertUTF8toUTF16(aName));
-  return PR_TRUE;
-}
-
 //----------------------------------------------------------------------
 nsresult GlobalPrinters::InitializeGlobalPrinters ()
 {
   if (PrintersAreAllocated()) {
     return NS_OK;
   }
 
   mGlobalPrinterList = new nsTArray<nsString>();
@@ -1096,19 +1084,25 @@ nsresult GlobalPrinters::InitializeGloba
   nsCOMPtr<nsIPrefBranch> pPrefs = do_GetService(NS_PREFSERVICE_CONTRACTID, &rv);
   if (NS_FAILED(rv))
     return rv;
       
 #ifdef USE_POSTSCRIPT
   nsPSPrinterList psMgr;
   if (NS_SUCCEEDED(psMgr.Init()) && psMgr.Enabled()) {
     /* Get the list of PostScript-module printers */
-    nsCStringArray printerList;
+    // XXX: this function is the only user of GetPrinterList
+    // So it may be interesting to convert the nsCStrings
+    // in this function, we would save one loop here
+    nsTArray<nsCString> printerList;
     psMgr.GetPrinterList(printerList);
-    printerList.EnumerateForwards(GlobalPrinterEnumFunc, mGlobalPrinterList);
+    for (PRUint32 i = 0; i < printerList.Length(); i++)
+    {
+      mGlobalPrinterList->AppendElement(NS_ConvertUTF8toUTF16(printerList[i]));
+    }
   }
 #endif /* USE_POSTSCRIPT */  
       
   /* If there are no printers available after all checks, return an error */
   if (!mGlobalPrinterList->Length())
   {
     /* Make sure we do not cache an empty printer list */
     FreeGlobalPrinters();
--- a/widget/src/gtk2/nsFilePicker.cpp
+++ b/widget/src/gtk2/nsFilePicker.cpp
@@ -273,18 +273,18 @@ nsFilePicker::AppendFilter(const nsAStri
     // No platform specific thing we can do here, really....
     return NS_OK;
   }
 
   nsCAutoString filter, name;
   CopyUTF16toUTF8(aFilter, filter);
   CopyUTF16toUTF8(aTitle, name);
 
-  mFilters.AppendCString(filter);
-  mFilterNames.AppendCString(name);
+  mFilters.AppendElement(filter);
+  mFilterNames.AppendElement(name);
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsFilePicker::SetDefaultString(const nsAString& aString)
 {
   mDefault = aString;
@@ -479,41 +479,41 @@ nsFilePicker::Show(PRInt16 *aReturn)
       defaultPath->GetNativePath(directory);
       gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(file_chooser),
                                           directory.get());
     }
   }
 
   gtk_dialog_set_default_response(GTK_DIALOG(file_chooser), GTK_RESPONSE_ACCEPT);
 
-  PRInt32 count = mFilters.Count();
+  PRInt32 count = mFilters.Length();
   for (PRInt32 i = 0; i < count; ++i) {
     // This is fun... the GTK file picker does not accept a list of filters
     // so we need to split out each string, and add it manually.
 
-    char **patterns = g_strsplit(mFilters[i]->get(), ";", -1);
+    char **patterns = g_strsplit(mFilters[i].get(), ";", -1);
     if (!patterns) {
       return NS_ERROR_OUT_OF_MEMORY;
     }
 
     GtkFileFilter *filter = gtk_file_filter_new();
     for (int j = 0; patterns[j] != NULL; ++j) {
       nsCAutoString caseInsensitiveFilter = MakeCaseInsensitiveShellGlob(g_strstrip(patterns[j]));
       gtk_file_filter_add_pattern(filter, caseInsensitiveFilter.get());
     }
 
     g_strfreev(patterns);
 
-    if (!mFilterNames[i]->IsEmpty()) {
+    if (!mFilterNames[i].IsEmpty()) {
       // If we have a name for our filter, let's use that.
-      const char *filter_name = mFilterNames[i]->get();
+      const char *filter_name = mFilterNames[i].get();
       gtk_file_filter_set_name(filter, filter_name);
     } else {
       // If we don't have a name, let's just use the filter pattern.
-      const char *filter_pattern = mFilters[i]->get();
+      const char *filter_pattern = mFilters[i].get();
       gtk_file_filter_set_name(filter, filter_pattern);
     }
 
     gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(file_chooser), filter);
 
     // Set the initially selected filter
     if (mSelectedType == i) {
       gtk_file_chooser_set_filter(GTK_FILE_CHOOSER(file_chooser), filter);
--- a/widget/src/gtk2/nsFilePicker.h
+++ b/widget/src/gtk2/nsFilePicker.h
@@ -37,17 +37,17 @@
 
 #ifndef nsFilePicker_h__
 #define nsFilePicker_h__
 
 #include <gtk/gtk.h>
 
 #include "nsBaseFilePicker.h"
 #include "nsString.h"
-#include "nsVoidArray.h"
+#include "nsTArray.h"
 #include "nsCOMArray.h"
 
 class nsIWidget;
 class nsILocalFile;
 
 class nsFilePicker : public nsBaseFilePicker
 {
 public:
@@ -84,16 +84,16 @@ protected:
   PRInt16   mMode;
   PRInt16   mSelectedType;
   PRBool    mAllowURLs;
   nsCString mFileURL;
   nsString  mTitle;
   nsString  mDefault;
   nsString  mDefaultExtension;
 
-  nsCStringArray mFilters;
-  nsCStringArray mFilterNames;
+  nsTArray<nsCString> mFilters;
+  nsTArray<nsCString> mFilterNames;
 
 private:
   static nsILocalFile *mPrevDisplayDirectory;
 };
 
 #endif
--- a/widget/src/gtk2/nsWindow.cpp
+++ b/widget/src/gtk2/nsWindow.cpp
@@ -1805,42 +1805,42 @@ nsWindow::SetTitle(const nsAString& aTit
 NS_IMETHODIMP
 nsWindow::SetIcon(const nsAString& aIconSpec)
 {
     if (!mShell)
         return NS_OK;
 
     nsCOMPtr<nsILocalFile> iconFile;
     nsCAutoString path;
-    nsCStringArray iconList;
+    nsTArray<nsCString> iconList;
 
     // Look for icons with the following suffixes appended to the base name.
     // The last two entries (for the old XPM format) will be ignored unless
     // no icons are found using the other suffixes. XPM icons are depricated.
 
     const char extensions[6][7] = { ".png", "16.png", "32.png", "48.png",
                                     ".xpm", "16.xpm" };
 
     for (PRUint32 i = 0; i < NS_ARRAY_LENGTH(extensions); i++) {
         // Don't bother looking for XPM versions if we found a PNG.
-        if (i == NS_ARRAY_LENGTH(extensions) - 2 && iconList.Count())
+        if (i == NS_ARRAY_LENGTH(extensions) - 2 && iconList.Length())
             break;
 
         nsAutoString extension;
         extension.AppendASCII(extensions[i]);
 
         ResolveIconName(aIconSpec, extension, getter_AddRefs(iconFile));
         if (iconFile) {
             iconFile->GetNativePath(path);
-            iconList.AppendCString(path);
+            iconList.AppendElement(path);
         }
     }
 
     // leave the default icon intact if no matching icons were found
-    if (iconList.Count() == 0)
+    if (iconList.Length() == 0)
         return NS_OK;
 
     return SetWindowIconList(iconList);
 }
 
 NS_IMETHODIMP
 nsWindow::SetMenuBar(void * aMenuBar)
 {
@@ -4685,22 +4685,22 @@ nsWindow::SetupPluginPort(void)
 
     XSync(GDK_DISPLAY(), False);
 #endif /* MOZ_X11 */
 
     return (void *)GDK_WINDOW_XWINDOW(mDrawingarea->inner_window);
 }
 
 nsresult
-nsWindow::SetWindowIconList(const nsCStringArray &aIconList)
+nsWindow::SetWindowIconList(const nsTArray<nsCString> &aIconList)
 {
     GList *list = NULL;
 
-    for (int i = 0; i < aIconList.Count(); ++i) {
-        const char *path = aIconList[i]->get();
+    for (PRUint32 i = 0; i < aIconList.Length(); ++i) {
+        const char *path = aIconList[i].get();
         LOG(("window [%p] Loading icon from %s\n", (void *)this, path));
 
         GdkPixbuf *icon = gdk_pixbuf_new_from_file(path, NULL);
         if (!icon)
             continue;
 
         list = g_list_append(list, icon);
     }
--- a/widget/src/gtk2/nsWindow.h
+++ b/widget/src/gtk2/nsWindow.h
@@ -75,16 +75,17 @@
 #endif
 
 #ifdef MOZ_LOGGING
 
 // make sure that logging is enabled before including prlog.h
 #define FORCE_PR_LOG
 
 #include "prlog.h"
+#include "nsTArray.h"
 
 extern PRLogModuleInfo *gWidgetLog;
 extern PRLogModuleInfo *gWidgetFocusLog;
 extern PRLogModuleInfo *gWidgetIMLog;
 extern PRLogModuleInfo *gWidgetDrawLog;
 
 #define LOG(args) PR_LOG(gWidgetLog, 4, args)
 #define LOGFOCUS(args) PR_LOG(gWidgetFocusLog, 4, args)
@@ -472,17 +473,17 @@ protected:
     PRUint32            mPreferredHeight;
 
 private:
     void               GetToplevelWidget(GtkWidget **aWidget);
     GtkWidget         *GetMozContainerWidget();
     void               GetContainerWindow(nsWindow  **aWindow);
     void               SetUrgencyHint(GtkWidget *top_window, PRBool state);
     void              *SetupPluginPort(void);
-    nsresult           SetWindowIconList(const nsCStringArray &aIconList);
+    nsresult           SetWindowIconList(const nsTArray<nsCString> &aIconList);
     void               SetDefaultIcon(void);
     void               InitButtonEvent(nsMouseEvent &aEvent, GdkEventButton *aGdkEvent);
     PRBool             DispatchCommandEvent(nsIAtom* aCommand);
 
     GtkWidget          *mShell;
     MozContainer       *mContainer;
     MozDrawingarea     *mDrawingarea;
 
--- a/widget/src/qt/nsFilePicker.cpp
+++ b/widget/src/qt/nsFilePicker.cpp
@@ -88,18 +88,18 @@ nsFilePicker::AppendFilter(const nsAStri
         // No platform specific thing we can do here, really....
         return NS_OK;
     }
 
     nsCAutoString filter, name;
     CopyUTF16toUTF8(aFilter, filter);
     CopyUTF16toUTF8(aTitle, name);
 
-    mFilters.AppendCString(filter);
-    mFilterNames.AppendCString(name);
+    mFilters.AppendElement(filter);
+    mFilterNames.AppendElement(name);
 
     return NS_OK;
 }
 
 /* attribute AString defaultString; */
 NS_IMETHODIMP
 nsFilePicker::GetDefaultString(nsAString & aDefaultString)
 {
@@ -219,19 +219,19 @@ nsFilePicker::Show(PRInt16 *aReturn)
         break;
     }
 
     mDialog->selectFile(QString::fromUtf16(mDefault.get()));
 
     mDialog->setDirectory(directory.get());
 
     QStringList filters;
-    PRInt32 count = mFilters.Count();
-    for (PRInt32 i = 0; i < count; ++i) {
-        filters.append( mFilters[i]->get() );
+    PRUint32 count = mFilters.Length();
+    for (PRUint32 i = 0; i < count; ++i) {
+        filters.append( mFilters[i].get() );
     }
     mDialog->setFilters(filters);
 
     switch (mDialog->exec()) {
     case QDialog::Accepted: {
         QStringList files = mDialog->selectedFiles();
         QString selected;
         if (!files.isEmpty())
--- a/widget/src/qt/nsFilePicker.h
+++ b/widget/src/qt/nsFilePicker.h
@@ -38,17 +38,17 @@
  *
  * ***** END LICENSE BLOCK ***** */
 #ifndef NSFILEPICKER_H
 #define NSFILEPICKER_H
 
 #include "nsBaseFilePicker.h"
 #include "nsString.h"
 #include "nsIURI.h"
-#include "nsVoidArray.h"
+#include "nsTArray.h"
 #include <qfiledialog.h>
 
 class nsIWidget;
 class nsILocalFile;
 class nsISupportsArray;
 class QFileDialog;
 
 class nsFilePicker : public nsBaseFilePicker
@@ -83,13 +83,13 @@ protected:
 
     PRInt16   mMode;
     PRInt16   mSelectedType;
     nsCString mFile;
     nsString  mTitle;
     nsString  mDefault;
     nsString  mDefaultExtension;
 
-    nsCStringArray mFilters;
-    nsCStringArray mFilterNames;
+    nsTArray<nsCString> mFilters;
+    nsTArray<nsCString> mFilterNames;
 };
 
 #endif
--- a/widget/src/qt/nsWindow.cpp
+++ b/widget/src/qt/nsWindow.cpp
@@ -871,42 +871,42 @@ nsWindow::SetTitle(const nsAString& aTit
 NS_IMETHODIMP
 nsWindow::SetIcon(const nsAString& aIconSpec)
 {
     if (!mDrawingArea)
         return NS_OK;
 
     nsCOMPtr<nsILocalFile> iconFile;
     nsCAutoString path;
-    nsCStringArray iconList;
+    nsTArray<nsCString> iconList;
 
     // Look for icons with the following suffixes appended to the base name.
     // The last two entries (for the old XPM format) will be ignored unless
     // no icons are found using the other suffixes. XPM icons are depricated.
 
     const char extensions[6][7] = { ".png", "16.png", "32.png", "48.png",
                                     ".xpm", "16.xpm" };
 
     for (PRUint32 i = 0; i < NS_ARRAY_LENGTH(extensions); i++) {
         // Don't bother looking for XPM versions if we found a PNG.
-        if (i == NS_ARRAY_LENGTH(extensions) - 2 && iconList.Count())
+        if (i == NS_ARRAY_LENGTH(extensions) - 2 && iconList.Length())
             break;
 
         nsAutoString extension;
         extension.AppendASCII(extensions[i]);
 
         ResolveIconName(aIconSpec, extension, getter_AddRefs(iconFile));
         if (iconFile) {
             iconFile->GetNativePath(path);
-            iconList.AppendCString(path);
+            iconList.AppendElement(path);
         }
     }
 
     // leave the default icon intact if no matching icons were found
-    if (iconList.Count() == 0)
+    if (iconList.Length() == 0)
         return NS_OK;
 
     return SetWindowIconList(iconList);
 }
 
 NS_IMETHODIMP
 nsWindow::ShowMenuBar(PRBool aShow)
 {
@@ -1997,17 +1997,17 @@ nsWindow::SetupPluginPort(void)
     XSync(Qt::Key_DISPLAY(), False);
 
     return (void *)Qt::Key_WINDOW_XWINDOW(mDrawingArea->inner_window);
 */
     return nsnull;
 }
 
 nsresult
-nsWindow::SetWindowIconList(const nsCStringArray &aIconList)
+nsWindow::SetWindowIconList(const nsTArray<nsCString> &aIconList)
 {
     qDebug("FIXME:>>>>>>Func:%s::%d\n", __PRETTY_FUNCTION__, __LINE__);
     return NS_OK;
 }
 
 void
 nsWindow::SetDefaultIcon(void)
 {
--- a/widget/src/qt/nsWindow.h
+++ b/widget/src/qt/nsWindow.h
@@ -59,16 +59,17 @@
 #endif
 
 #ifdef MOZ_LOGGING
 
 // make sure that logging is enabled before including prlog.h
 #define FORCE_PR_LOG
 
 #include "prlog.h"
+#include "nsTArray.h"
 
 extern PRLogModuleInfo *gWidgetLog;
 extern PRLogModuleInfo *gWidgetFocusLog;
 extern PRLogModuleInfo *gWidgetIMLog;
 extern PRLogModuleInfo *gWidgetDrawLog;
 
 #define LOG(args) PR_LOG(gWidgetLog, 4, args)
 #define LOGFOCUS(args) PR_LOG(gWidgetFocusLog, 4, args)
@@ -344,17 +345,17 @@ protected:
     void               ThemeChanged(void);
 
    gfxASurface        *GetThebesSurface();
 
 private:
     void               GetToplevelWidget(QWidget **aWidget);
     void               SetUrgencyHint(QWidget *top_window, PRBool state);
     void              *SetupPluginPort(void);
-    nsresult           SetWindowIconList(const nsCStringArray &aIconList);
+    nsresult           SetWindowIconList(const nsTArray<nsCString> &aIconList);
     void               SetDefaultIcon(void);
     void               InitButtonEvent(nsMouseEvent &event, QMouseEvent *aEvent, int aClickCount = 1);
     PRBool             DispatchCommandEvent(nsIAtom* aCommand);
     QWidget           *createQWidget(QWidget *parent, nsWidgetInitData *aInitData);
 
     QWidget            *mDrawingArea;
     MozQWidget *mMozQWidget;
 
--- a/xpcom/base/nsCycleCollector.cpp
+++ b/xpcom/base/nsCycleCollector.cpp
@@ -138,17 +138,17 @@
 #include "prtime.h"
 #include "nsPrintfCString.h"
 #include "nsTArray.h"
 #include "nsIObserverService.h"
 #include "nsIConsoleService.h"
 #include "nsServiceManagerUtils.h"
 #include "nsThreadUtils.h"
 #include "nsTPtrArray.h"
-#include "nsVoidArray.h" // for nsCStringArray
+#include "nsTArray.h"
 
 #include <stdio.h>
 #include <string.h>
 #ifdef WIN32
 #include <io.h>
 #include <process.h>
 #endif
 
@@ -466,17 +466,17 @@ struct PtrInfo
     PRUint32 mSCCIndex; // strongly connected component
 
     // For finding roots in ExplainLiveExpectedGarbage (when nodes
     // expected to be garbage are black).
     ReversedEdge* mReversedEdges; // linked list
     PtrInfo* mShortestPathToExpectedGarbage;
     nsCString* mShortestPathToExpectedGarbageEdgeName;
 
-    nsCStringArray mEdgeNames;
+    nsTArray<nsCString> mEdgeNames;
 #endif
 
     PtrInfo(void *aPointer, nsCycleCollectionParticipant *aParticipant
             IF_DEBUG_CC_PARAM(PRUint32 aLangID)
             )
         : mPointer(aPointer),
           mParticipant(aParticipant),
           mColor(grey),
@@ -494,17 +494,17 @@ struct PtrInfo
           mShortestPathToExpectedGarbageEdgeName(nsnull)
 #endif
     {
     }
 
 #ifdef DEBUG_CC
     void Destroy() {
         PL_strfree(mName);
-        mEdgeNames.~nsCStringArray();
+        mEdgeNames.~nsTArray<nsCString>();
     }
 #endif
 
     // Allow NodePool::Block's constructor to compile.
     PtrInfo() {
         NS_NOTREACHED("should never be called");
     }
 };
@@ -1402,17 +1402,17 @@ GCGraphBuilder::NoteXPCOMChild(nsISuppor
     nsXPCOMCycleCollectionParticipant *cp;
     ToParticipant(child, &cp);
     if (cp) {
         PtrInfo *childPi = AddNode(child, cp, nsIProgrammingLanguage::CPLUSPLUS);
         if (!childPi)
             return;
         mEdgeBuilder.Add(childPi);
 #ifdef DEBUG_CC
-        mCurrPi->mEdgeNames.AppendCString(edgeName);
+        mCurrPi->mEdgeNames.AppendElement(edgeName);
 #endif
         ++childPi->mInternalRefs;
     }
 }
 
 NS_IMETHODIMP_(void)
 GCGraphBuilder::NoteNativeChild(void *child,
                                 nsCycleCollectionParticipant *participant)
@@ -1426,17 +1426,17 @@ GCGraphBuilder::NoteNativeChild(void *ch
 
     NS_ASSERTION(participant, "Need a nsCycleCollectionParticipant!");
 
     PtrInfo *childPi = AddNode(child, participant, nsIProgrammingLanguage::CPLUSPLUS);
     if (!childPi)
         return;
     mEdgeBuilder.Add(childPi);
 #ifdef DEBUG_CC
-    mCurrPi->mEdgeNames.AppendCString(edgeName);
+    mCurrPi->mEdgeNames.AppendElement(edgeName);
 #endif
     ++childPi->mInternalRefs;
 }
 
 NS_IMETHODIMP_(void)
 GCGraphBuilder::NoteScriptChild(PRUint32 langID, void *child) 
 {
 #ifdef DEBUG_CC
@@ -1461,17 +1461,17 @@ GCGraphBuilder::NoteScriptChild(PRUint32
     if (!cp)
         return;
 
     PtrInfo *childPi = AddNode(child, cp, langID);
     if (!childPi)
         return;
     mEdgeBuilder.Add(childPi);
 #ifdef DEBUG_CC
-    mCurrPi->mEdgeNames.AppendCString(edgeName);
+    mCurrPi->mEdgeNames.AppendElement(edgeName);
 #endif
     ++childPi->mInternalRefs;
 }
 
 #ifdef DEBUG_CC
 NS_IMETHODIMP_(void)
 GCGraphBuilder::NoteNextEdgeName(const char* name)
 {
@@ -2817,17 +2817,17 @@ nsCycleCollector::CreateReversedEdges()
     ReversedEdge *current = mGraph.mReversedEdges;
     NodePool::Enumerator buildQueue(mGraph.mNodes);
     while (!buildQueue.IsDone()) {
         PtrInfo *pi = buildQueue.GetNext();
         PRInt32 i = 0;
         for (EdgePool::Iterator e = pi->mFirstChild, e_end = pi->mLastChild;
              e != e_end; ++e) {
             current->mTarget = pi;
-            current->mEdgeName = pi->mEdgeNames.CStringAt(i);
+            current->mEdgeName = pi->mEdgeNames[i];
             current->mNext = (*e)->mReversedEdges;
             (*e)->mReversedEdges = current;
             ++current;
             ++i;
         }
     }
     NS_ASSERTION(current - mGraph.mReversedEdges == ptrdiff_t(edgeCount),
                  "misallocation");
--- a/xpcom/ds/nsINIParserImpl.cpp
+++ b/xpcom/ds/nsINIParserImpl.cpp
@@ -36,17 +36,17 @@
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsINIParserImpl.h"
 
 #include "nsILocalFile.h"
 
 #include "nsINIParser.h"
 #include "nsStringEnumerator.h"
-#include "nsVoidArray.h"
+#include "nsTArray.h"
 
 class nsINIParserImpl :
   public nsIINIParser
 {
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSIINIPARSER
 
@@ -98,53 +98,53 @@ nsINIParserFactory::LockFactory(PRBool a
 }
 
 NS_IMPL_ISUPPORTS1(nsINIParserImpl,
                    nsIINIParser)
 
 static PRBool
 SectionCB(const char* aSection, void *aClosure)
 {
-  nsCStringArray *strings = static_cast<nsCStringArray*>(aClosure);
+  nsTArray<nsCString> *strings = static_cast<nsTArray<nsCString>*>(aClosure);
 
-  strings->AppendCString(nsDependentCString(aSection));
+  strings->AppendElement(nsDependentCString(aSection));
   return PR_TRUE;
 }
 
 NS_IMETHODIMP
 nsINIParserImpl::GetSections(nsIUTF8StringEnumerator* *aResult)
 {
-  nsCStringArray *strings = new nsCStringArray;
+  nsTArray<nsCString> *strings = new nsTArray<nsCString>;
   if (!strings)
     return NS_ERROR_OUT_OF_MEMORY;
 
   nsresult rv = mParser.GetSections(SectionCB, strings);
   if (NS_SUCCEEDED(rv))
     rv = NS_NewUTF8StringEnumerator(aResult, strings);
 
   if (NS_FAILED(rv))
     delete strings;
 
   return rv;
 }
 
 static PRBool
 KeyCB(const char* aKey, const char *aValue, void *aClosure)
 {
-  nsCStringArray *strings = static_cast<nsCStringArray*>(aClosure);
+  nsTArray<nsCString> *strings = static_cast<nsTArray<nsCString>*>(aClosure);
 
-  strings->AppendCString(nsDependentCString(aKey));
+  strings->AppendElement(nsDependentCString(aKey));
   return PR_TRUE;
 }
 
 NS_IMETHODIMP
 nsINIParserImpl::GetKeys(const nsACString& aSection,
                          nsIUTF8StringEnumerator* *aResult)
 {
-  nsCStringArray *strings = new nsCStringArray;
+  nsTArray<nsCString> *strings = new nsTArray<nsCString>;
   if (!strings)
     return NS_ERROR_OUT_OF_MEMORY;
 
   nsresult rv = mParser.GetStrings(PromiseFlatCString(aSection).get(),
                                    KeyCB, strings);
   if (NS_SUCCEEDED(rv))
     rv = NS_NewUTF8StringEnumerator(aResult, strings);
 
--- a/xpcom/ds/nsStringEnumerator.cpp
+++ b/xpcom/ds/nsStringEnumerator.cpp
@@ -53,25 +53,25 @@ class nsStringEnumerator : public nsIStr
                            public nsIUTF8StringEnumerator,
                            public nsISimpleEnumerator
 {
 public:
     nsStringEnumerator(const nsTArray<nsString>* aArray, PRBool aOwnsArray) :
         mArray(aArray), mIndex(0), mOwnsArray(aOwnsArray), mIsUnicode(PR_TRUE)
     {}
     
-    nsStringEnumerator(const nsCStringArray* aArray, PRBool aOwnsArray) :
+    nsStringEnumerator(const nsTArray<nsCString>* aArray, PRBool aOwnsArray) :
         mCArray(aArray), mIndex(0), mOwnsArray(aOwnsArray), mIsUnicode(PR_FALSE)
     {}
 
     nsStringEnumerator(const nsTArray<nsString>* aArray, nsISupports* aOwner) :
         mArray(aArray), mIndex(0), mOwner(aOwner), mOwnsArray(PR_FALSE), mIsUnicode(PR_TRUE)
     {}
     
-    nsStringEnumerator(const nsCStringArray* aArray, nsISupports* aOwner) :
+    nsStringEnumerator(const nsTArray<nsCString>* aArray, nsISupports* aOwner) :
         mCArray(aArray), mIndex(0), mOwner(aOwner), mOwnsArray(PR_FALSE), mIsUnicode(PR_FALSE)
     {}
 
     NS_DECL_ISUPPORTS
     NS_DECL_NSIUTF8STRINGENUMERATOR
 
     // have to declare nsIStringEnumerator manually, because of
     // overlapping method names
@@ -82,27 +82,27 @@ private:
     ~nsStringEnumerator() {
         if (mOwnsArray) {
             // const-casting is safe here, because the NS_New*
             // constructors make sure mOwnsArray is consistent with
             // the constness of the objects
             if (mIsUnicode)
                 delete const_cast<nsTArray<nsString>*>(mArray);
             else
-                delete const_cast<nsCStringArray*>(mCArray);
+                delete const_cast<nsTArray<nsCString>*>(mCArray);
         }
     }
 
     union {
         const nsTArray<nsString>* mArray;
-        const nsCStringArray* mCArray;
+        const nsTArray<nsCString>* mCArray;
     };
 
     inline PRUint32 Count() {
-        return mIsUnicode ? mArray->Length() : mCArray->Count();
+        return mIsUnicode ? mArray->Length() : mCArray->Length();
     }
     
     PRUint32 mIndex;
 
     // the owner allows us to hold a strong reference to the object
     // that owns the array. Having a non-null value in mOwner implies
     // that mOwnsArray is PR_FALSE, because we rely on the real owner
     // to release the array
@@ -139,45 +139,45 @@ nsStringEnumerator::GetNext(nsISupports*
         
         stringImpl->SetData(mArray->ElementAt(mIndex++));
         *aResult = stringImpl;
     }
     else {
         nsSupportsCStringImpl* cstringImpl = new nsSupportsCStringImpl();
         if (!cstringImpl) return NS_ERROR_OUT_OF_MEMORY;
 
-        cstringImpl->SetData(*mCArray->CStringAt(mIndex++));
+        cstringImpl->SetData(mCArray->ElementAt(mIndex++));
         *aResult = cstringImpl;
     }
     NS_ADDREF(*aResult);
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsStringEnumerator::GetNext(nsAString& aResult)
 {
     NS_ENSURE_TRUE(mIndex < Count(), NS_ERROR_UNEXPECTED);
 
     if (mIsUnicode)
         aResult = mArray->ElementAt(mIndex++);
     else
-        CopyUTF8toUTF16(*mCArray->CStringAt(mIndex++), aResult);
+        CopyUTF8toUTF16(mCArray->ElementAt(mIndex++), aResult);
     
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsStringEnumerator::GetNext(nsACString& aResult)
 {
     NS_ENSURE_TRUE(mIndex < Count(), NS_ERROR_UNEXPECTED);
     
     if (mIsUnicode)
         CopyUTF16toUTF8(mArray->ElementAt(mIndex++), aResult);
     else
-        aResult = *mCArray->CStringAt(mIndex++);
+        aResult = mCArray->ElementAt(mIndex++);
     
     return NS_OK;
 }
 
 template<class T>
 static inline nsresult
 StringEnumeratorTail(T** aResult NS_INPARAM)
 {
@@ -200,17 +200,17 @@ NS_NewStringEnumerator(nsIStringEnumerat
     
     *aResult = new nsStringEnumerator(aArray, aOwner);
     return StringEnumeratorTail(aResult);
 }
 
 
 NS_COM nsresult
 NS_NewUTF8StringEnumerator(nsIUTF8StringEnumerator** aResult,
-                           const nsCStringArray* aArray, nsISupports* aOwner)
+                           const nsTArray<nsCString>* aArray, nsISupports* aOwner)
 {
     NS_ENSURE_ARG_POINTER(aResult);
     NS_ENSURE_ARG_POINTER(aArray);
     
     *aResult = new nsStringEnumerator(aArray, aOwner);
     return StringEnumeratorTail(aResult);
 }
 
@@ -222,17 +222,17 @@ NS_NewAdoptingStringEnumerator(nsIString
     NS_ENSURE_ARG_POINTER(aArray);
     
     *aResult = new nsStringEnumerator(aArray, PR_TRUE);
     return StringEnumeratorTail(aResult);
 }
 
 NS_COM nsresult
 NS_NewAdoptingUTF8StringEnumerator(nsIUTF8StringEnumerator** aResult,
-                                   nsCStringArray* aArray)
+                                   nsTArray<nsCString>* aArray)
 {
     NS_ENSURE_ARG_POINTER(aResult);
     NS_ENSURE_ARG_POINTER(aArray);
     
     *aResult = new nsStringEnumerator(aArray, PR_TRUE);
     return StringEnumeratorTail(aResult);
 }
 
@@ -245,17 +245,17 @@ NS_NewStringEnumerator(nsIStringEnumerat
     NS_ENSURE_ARG_POINTER(aArray);
     
     *aResult = new nsStringEnumerator(aArray, PR_FALSE);
     return StringEnumeratorTail(aResult);
 }
 
 NS_COM nsresult
 NS_NewUTF8StringEnumerator(nsIUTF8StringEnumerator** aResult,
-                           const nsCStringArray* aArray)
+                           const nsTArray<nsCString>* aArray)
 {
     NS_ENSURE_ARG_POINTER(aResult);
     NS_ENSURE_ARG_POINTER(aArray);
     
     *aResult = new nsStringEnumerator(aArray, PR_FALSE);
     return StringEnumeratorTail(aResult);
 }
 
--- a/xpcom/ds/nsStringEnumerator.h
+++ b/xpcom/ds/nsStringEnumerator.h
@@ -32,17 +32,17 @@
  * decision by deleting the provisions above and replace them with the notice
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsIStringEnumerator.h"
-#include "nsVoidArray.h"
+#include "nsString.h"
 #include "nsTArray.h"
 
 // nsIStringEnumerator/nsIUTF8StringEnumerator implementations
 //
 // Currently all implementations support both interfaces. The
 // constructors below provide the most common interface for the given
 // type (i.e. nsIStringEnumerator for PRUnichar* strings, and so
 // forth) but any resulting enumerators can be queried to the other
@@ -61,63 +61,63 @@
 // The non-adopting enumerator requires that the array sticks around
 // at least as long as the enumerator does. These are for constant
 // string arrays that the enumerator does not own, this could be used
 // in VERY specialized cases such as when the provider KNOWS that the
 // string enumerator will be consumed immediately, or will at least
 // outlast the array.
 // For example:
 //
-// nsCStringArray array;
+// nsTArray<nsCString> array;
 // array.AppendCString("abc");
 // array.AppendCString("def");
 // NS_NewStringEnumerator(&enumerator, &array, PR_TRUE);
 //
 // // call some internal method which iterates the enumerator
 // InternalMethod(enumerator);
 // NS_RELEASE(enumerator);
 //
 NS_COM nsresult
 NS_NewStringEnumerator(nsIStringEnumerator** aResult NS_OUTPARAM,
                        const nsTArray<nsString>* aArray,
                        nsISupports* aOwner);
 NS_COM nsresult
 NS_NewUTF8StringEnumerator(nsIUTF8StringEnumerator** aResult NS_OUTPARAM,
-                           const nsCStringArray* aArray);
+                           const nsTArray<nsCString>* aArray);
 
 NS_COM nsresult
 NS_NewStringEnumerator(nsIStringEnumerator** aResult NS_OUTPARAM,
                        const nsTArray<nsString>* aArray);
 
 // Adopting string enumerators assume ownership of the array and will
 // call |operator delete| on the array when the enumerator is destroyed
 // this is useful when the provider creates an array solely for the
 // purpose of creating the enumerator.
 // For example:
 //
-// nsCStringArray* array = new nsCStringArray;
+// nsTArray<nsCString>* array = new nsTArray<nsCString>;
 // array->AppendString("abcd");
 // NS_NewAdoptingStringEnumerator(&result, array);
 NS_COM nsresult
 NS_NewAdoptingStringEnumerator(nsIStringEnumerator** aResult NS_OUTPARAM,
                                nsTArray<nsString>* aArray);
 
 NS_COM nsresult
 NS_NewAdoptingUTF8StringEnumerator(nsIUTF8StringEnumerator** aResult NS_OUTPARAM,
-                                   nsCStringArray* aArray);
+                                   nsTArray<nsCString>* aArray);
 
 
 // these versions take a refcounted "owner" which will be addreffed
 // when the enumerator is created, and destroyed when the enumerator
 // is released. This allows providers to give non-owning pointers to
 // ns*StringArray member variables without worrying about lifetime
 // issues
 // For example:
 //
 // nsresult MyClass::Enumerate(nsIUTF8StringEnumerator** aResult) {
 //     mCategoryList->AppendString("abcd");
 //     return NS_NewStringEnumerator(aResult, mCategoryList, this);
 // }
 //
 NS_COM nsresult
 NS_NewUTF8StringEnumerator(nsIUTF8StringEnumerator** aResult NS_OUTPARAM,
-                           const nsCStringArray* aArray,
+                           const nsTArray<nsCString>* aArray,
                            nsISupports* aOwner);
--- a/xpcom/glue/nsStringAPI.cpp
+++ b/xpcom/glue/nsStringAPI.cpp
@@ -1141,8 +1141,40 @@ CaseInsensitiveCompare(const char *a, co
     if (la == lb)
       continue;
 
     return la < lb ? -1 : 1;
   }
 
   return 0;
 }
+
+PRBool
+ParseString(const nsACString& aSource, char aDelimiter, 
+            nsTArray<nsCString>& aArray)
+{
+  PRInt32 start = 0;
+  PRInt32 end = aSource.Length();
+
+  PRUint32 oldLength = aArray.Length();
+
+  for (;;) {
+    PRInt32 delimiter = aSource.FindChar(aDelimiter, start);
+    if (delimiter < 0) {
+      delimiter = end;
+    }
+
+    if (delimiter != start) {
+      if (!aArray.AppendElement(Substring(aSource, start, delimiter - start))) {
+        aArray.RemoveElementsAt(oldLength, aArray.Length() - oldLength);
+        return PR_FALSE;
+      }
+    }
+
+    if (delimiter == end)
+      break;
+    start = ++delimiter;
+    if (start == end)
+      break;
+  }
+
+  return PR_TRUE;
+}
--- a/xpcom/glue/nsStringAPI.h
+++ b/xpcom/glue/nsStringAPI.h
@@ -48,16 +48,17 @@
 #endif
 
 #ifndef nsStringAPI_h__
 #define nsStringAPI_h__
 
 #include "nsXPCOMStrings.h"
 #include "nsISupportsImpl.h"
 #include "prlog.h"
+#include "nsTArray.h"
 
 class nsAString
 {
 public:
   typedef PRUnichar  char_type;
   typedef nsAString  self_type;
   typedef PRUint32   size_type;
   typedef PRUint32   index_type;
@@ -1413,9 +1414,12 @@ ToNewUnicode(const nsAString& aStr)
 }
 
 typedef nsString PromiseFlatString;
 typedef nsCString PromiseFlatCString;
 
 typedef nsCString nsCAutoString;
 typedef nsString nsAutoString;
 
+NS_HIDDEN_(PRBool) ParseString(const nsACString& aAstring, char aDelimiter, 
+                               nsTArray<nsCString>& aArray);
+
 #endif // nsStringAPI_h__
--- a/xpcom/glue/nsVoidArray.cpp
+++ b/xpcom/glue/nsVoidArray.cpp
@@ -932,56 +932,16 @@ nsStringArray::EnumerateBackwards(nsStri
 //----------------------------------------------------------------
 // nsCStringArray
 
 nsCStringArray::nsCStringArray(void)
   : nsVoidArray()
 {
 }
 
-// Parses a given string using the delimiter passed in and appends items
-// parsed to the array.
-PRBool
-nsCStringArray::ParseString(const char* string, const char* delimiter)
-{
-  if (string && *string && delimiter && *delimiter) {
-    char *rest = strdup(string);
-    if (!rest)
-      return PR_FALSE;
-    char *newStr = rest;
-    char *token = NS_strtok(delimiter, &newStr);
-
-    PRInt32 count = Count();
-    while (token) {
-      if (*token) {
-        /* calling AppendElement(void*) to avoid extra nsCString copy */
-        nsCString *cstring = new nsCString(token);
-        if (cstring && !AppendElement(cstring)) {
-          // AppendElement failed, release and null cstring so we fall
-          // through to the case below.
-          delete cstring;
-          cstring = nsnull;
-        }
-        if (!cstring) {
-          // We've run out of memory. Remove all newly appended elements from
-          // our array so we don't leave ourselves in a partially added state.
-          // When we return, the array will be precisely as it was when this
-          // function was called.
-          RemoveElementsAt(count, Count() - count);
-          free(rest);
-          return PR_FALSE;
-        }
-      }
-      token = NS_strtok(delimiter, &newStr);
-    }
-    free(rest);
-  }
-  return PR_TRUE;
-}
-
 nsCStringArray::nsCStringArray(PRInt32 aCount)
   : nsVoidArray(aCount)
 {
 }
 
 nsCStringArray::~nsCStringArray(void)
 {
   Clear();
--- a/xpcom/glue/nsVoidArray.h
+++ b/xpcom/glue/nsVoidArray.h
@@ -265,23 +265,16 @@ class NS_COM_GLUE nsCStringArray: privat
 {
 public:
   nsCStringArray(void);
   nsCStringArray(PRInt32 aCount); // Storage for aCount elements will be pre-allocated
   ~nsCStringArray(void);
 
   nsCStringArray& operator=(const nsCStringArray& other);
 
-  // Parses a given string using the delimiter passed in. If the array
-  // already has some elements, items parsed from string will be appended 
-  // to array. For example, array.ParseString("a,b,c", ","); will add strings
-  // "a", "b" and "c" to the array. Parsing process has the same tokenizing 
-  // behavior as strtok().  
-  PRBool ParseString(const char* string, const char* delimiter);
-
   PRInt32 Count(void) const {
     return nsVoidArray::Count();
   }
 
   void CStringAt(PRInt32 aIndex, nsACString& aCString) const;
   nsCString* CStringAt(PRInt32 aIndex) const;
   nsCString* operator[](PRInt32 aIndex) const { return CStringAt(aIndex); }
 
--- a/xpcom/string/public/nsReadableUtils.h
+++ b/xpcom/string/public/nsReadableUtils.h
@@ -43,16 +43,17 @@
   /**
    * I guess all the routines in this file are all mis-named.
    * According to our conventions, they should be |NS_xxx|.
    */
 
 #ifndef nsAString_h___
 #include "nsAString.h"
 #endif
+#include "nsTArray.h"
 
 inline size_t Distance( const nsReadingIterator<PRUnichar>& start, const nsReadingIterator<PRUnichar>& end )
   {
     return end.get() - start.get();
   }
 inline size_t Distance( const nsReadingIterator<char>& start, const nsReadingIterator<char>& end )
   {
     return end.get() - start.get();
@@ -247,16 +248,18 @@ NS_COM PRBool IsASCII( const nsACString&
    * Also note that it regards UTF-8 sequences corresponding to 
    * codepoints above 0x10FFFF as invalid in accordance with 
    * http://www.ietf.org/internet-drafts/draft-yergeau-rfc2279bis-04.txt
    *
    * @param aString an 8-bit wide string to scan
    */
 NS_COM PRBool IsUTF8( const nsACString& aString );
 
+NS_COM PRBool ParseString(const nsACString& aAstring, char aDelimiter, 
+                          nsTArray<nsCString>& aArray);
 
   /**
    * Converts case in place in the argument string.
    */
 NS_COM void ToUpperCase( nsACString& );
 
 NS_COM void ToLowerCase( nsACString& );
 
--- a/xpcom/string/src/nsReadableUtils.cpp
+++ b/xpcom/string/src/nsReadableUtils.cpp
@@ -786,16 +786,51 @@ ToLowerCase( const nsACString& aSource, 
     nsACString::iterator toBegin;
     if (!SetLengthForWritingC(aDest, aSource.Length()))
         return;
 
     CopyToLowerCase converter(aDest.BeginWriting(toBegin));
     copy_string(aSource.BeginReading(fromBegin), aSource.EndReading(fromEnd), converter);
   }
 
+NS_COM
+PRBool
+ParseString(const nsACString& aSource, char aDelimiter, 
+            nsTArray<nsCString>& aArray)
+  {
+    nsACString::const_iterator start, end;
+    aSource.BeginReading(start);
+    aSource.EndReading(end);
+
+    PRUint32 oldLength = aArray.Length();
+
+    for (;;)
+      {
+        nsACString::const_iterator delimiter = start;
+        FindCharInReadable(aDelimiter, delimiter, end);
+
+        if (delimiter != start)
+          {
+            if (!aArray.AppendElement(Substring(start, delimiter)))
+              {
+                aArray.RemoveElementsAt(oldLength, aArray.Length() - oldLength);
+                return PR_FALSE;
+              }
+          }
+
+        if (delimiter == end)
+          break;
+        start = ++delimiter;
+        if (start == end)
+          break;
+      }
+
+    return PR_TRUE;
+  }
+
 template <class StringT, class IteratorT, class Comparator>
 PRBool
 FindInReadable_Impl( const StringT& aPattern, IteratorT& aSearchStart, IteratorT& aSearchEnd, const Comparator& compare )
   {
     PRBool found_it = PR_FALSE;
 
       // only bother searching at all if we're given a non-empty range to search
     if ( aSearchStart != aSearchEnd )
--- a/xpcom/tests/TestStrings.cpp
+++ b/xpcom/tests/TestStrings.cpp
@@ -916,16 +916,60 @@ PRBool test_string_tointeger()
   for (const ToIntegerTest* t = kToIntegerTests; t->str; ++t) {
     PRInt32 result = nsCAutoString(t->str).ToInteger(&rv, t->radix);
     if (rv != t->rv || result != t->result)
       return PR_FALSE;
   }
   return PR_TRUE;
 }
 
+static PRBool test_parse_string_helper(const char* str, char separator, int len,
+                                       const char* s1, const char* s2)
+{
+  nsCString data(str);
+  nsTArray<nsCString> results;
+  if (!ParseString(data, separator, results))
+    return PR_FALSE;
+  if (int(results.Length()) != len)
+    return PR_FALSE;
+  const char* strings[] = { s1, s2 };
+  for (int i = 0; i < len; ++i) {
+    if (!results[i].Equals(strings[i]))
+      return PR_FALSE;
+  }
+  return PR_TRUE;
+}
+
+static PRBool test_parse_string_helper0(const char* str, char separator)
+{
+  return test_parse_string_helper(str, separator, 0, nsnull, nsnull);
+}
+
+static PRBool test_parse_string_helper1(const char* str, char separator, const char* s1)
+{
+  return test_parse_string_helper(str, separator, 1, s1, nsnull);
+}
+
+static PRBool test_parse_string_helper2(const char* str, char separator, const char* s1, const char* s2)
+{
+  return test_parse_string_helper(str, separator, 2, s1, s2);
+}
+
+static PRBool test_parse_string()
+{
+  return test_parse_string_helper1("foo, bar", '_', "foo, bar") &&
+         test_parse_string_helper2("foo, bar", ',', "foo", " bar") &&
+         test_parse_string_helper2("foo, bar ", ' ', "foo,", "bar") &&
+         test_parse_string_helper2("foo,bar", 'o', "f", ",bar") &&
+         test_parse_string_helper0("", '_') &&
+         test_parse_string_helper0("  ", ' ') &&
+         test_parse_string_helper1(" foo", ' ', "foo") &&
+         test_parse_string_helper1("  foo", ' ', "foo");
+}
+
 //----
 
 typedef PRBool (*TestFunc)();
 
 static const struct Test
   {
     const char* name;
     TestFunc    func;
@@ -960,16 +1004,17 @@ tests[] =
     { "test_appendint64", test_appendint64 },
     { "test_appendfloat", test_appendfloat },
     { "test_findcharinset", test_findcharinset },
     { "test_rfindcharinset", test_rfindcharinset },
     { "test_stringbuffer", test_stringbuffer },
     { "test_voided", test_voided },
     { "test_voided_autostr", test_voided_autostr },
     { "test_string_tointeger", test_string_tointeger },
+    { "test_parse_string", test_parse_string },
     { nsnull, nsnull }
   };
 
 }
 
 using namespace TestStrings;
 
 int main(int argc, char **argv)
--- a/xpcom/tests/external/TestMinStringAPI.cpp
+++ b/xpcom/tests/external/TestMinStringAPI.cpp
@@ -894,16 +894,60 @@ static PRBool test_comparisons()
 
   result = (shortCString4 >= shortCString3);
   if (!result)
     return PR_FALSE;
 
   return PR_TRUE;
 }
 
+static PRBool test_parse_string_helper(const char* str, char separator, int len,
+                                       const char* s1, const char* s2)
+{
+  nsCString data(str);
+  nsTArray<nsCString> results;
+  if (!ParseString(data, separator, results))
+    return PR_FALSE;
+  if (int(results.Length()) != len)
+    return PR_FALSE;
+  const char* strings[] = { s1, s2 };
+  for (int i = 0; i < len; ++i) {
+    if (!results[i].Equals(strings[i]))
+      return PR_FALSE;
+  }
+  return PR_TRUE;
+}
+
+static PRBool test_parse_string_helper0(const char* str, char separator)
+{
+  return test_parse_string_helper(str, separator, 0, nsnull, nsnull);
+}
+
+static PRBool test_parse_string_helper1(const char* str, char separator, const char* s1)
+{
+  return test_parse_string_helper(str, separator, 1, s1, nsnull);
+}
+
+static PRBool test_parse_string_helper2(const char* str, char separator, const char* s1, const char* s2)
+{
+  return test_parse_string_helper(str, separator, 2, s1, s2);
+}
+
+static PRBool test_parse_string()
+{
+  return test_parse_string_helper1("foo, bar", '_', "foo, bar") &&
+         test_parse_string_helper2("foo, bar", ',', "foo", " bar") &&
+         test_parse_string_helper2("foo, bar ", ' ', "foo,", "bar") &&
+         test_parse_string_helper2("foo,bar", 'o', "f", ",bar") &&
+         test_parse_string_helper0("", '_') &&
+         test_parse_string_helper0("  ", ' ') &&
+         test_parse_string_helper1(" foo", ' ', "foo") &&
+         test_parse_string_helper1("  foo", ' ', "foo");
+}
+
 //----
 
 typedef PRBool (*TestFunc)();
 
 static const struct Test
   {
     const char* name;
     TestFunc    func;
@@ -921,16 +965,17 @@ tests[] =
     { "test_adopt", test_adopt },
     { "test_adopt_sub", test_adopt_sub },
     { "test_mutation", test_mutation },
     { "test_stripchars", test_stripchars },
     { "test_trim", test_trim },
     { "test_find", test_find },
     { "test_compressws", test_compressws },
     { "test_comparisons", test_comparisons },
+    { "test_parse_string", test_parse_string },
     { nsnull, nsnull }
   };
 
 //----
 
 int main(int argc, char **argv)
   {
     int count = 1;
--- a/xpfe/components/intl/nsCharsetMenu.cpp
+++ b/xpfe/components/intl/nsCharsetMenu.cpp
@@ -55,16 +55,17 @@
 #include "nsIPrefBranch.h"
 #include "nsIPrefBranch2.h"
 #include "nsIPrefLocalizedString.h"
 #include "nsICurrentCharsetListener.h"
 #include "nsQuickSort.h"
 #include "nsIObserver.h"
 #include "nsStringEnumerator.h"
 #include "nsVoidArray.h"
+#include "nsTArray.h"
 #include "nsIObserverService.h"
 #include "nsIRequestObserver.h"
 #include "nsITimelineService.h"
 #include "nsCRT.h"
 #include "prmem.h"
 #include "nsCycleCollectionParticipant.h"
 
 //----------------------------------------------------------------------------
@@ -107,25 +108,16 @@ DEFINE_RDF_VOCAB(RDF_NAMESPACE_URI, NC, 
 #define kMailviewCacheSizePrefKey   "intl.charsetmenu.browser.cache.size"
 
 #define kComposerStaticPrefKey      "intl.charsetmenu.browser.static"
 #define kComposerCachePrefKey       "intl.charsetmenu.composer.cache"
 #define kComposerCacheSizePrefKey   "intl.charsetmenu.browser.cache.size"
 
 #define kMaileditPrefKey            "intl.charsetmenu.mailedit"
 
-static void CloneCStringArray(const nsCStringArray& src, nsCStringArray& dest)
-{
-  PRUint32 count = src.Count();
-  PRUint32 i;
-  for (i=0; i<count; i++) {
-    dest.AppendCString(*src.CStringAt(i));
-  }
-}
-
 //----------------------------------------------------------------------------
 // Class nsMenuEntry [declaration]
 
 /**
  * A little class holding all data needed for a menu item.
  *
  * @created         18/Apr/2000
  * @author  Catalin Rotaru [CATA]
@@ -203,72 +195,72 @@ private:
   PRInt32       mComposerCacheStart;
   PRInt32       mComposerCacheSize;
   PRInt32       mComposerMenuRDFPosition;
 
   nsCOMPtr<nsIRDFService>               mRDFService;
   nsCOMPtr<nsICharsetConverterManager> mCCManager;
   nsCOMPtr<nsIPrefBranch>               mPrefs;
   nsCOMPtr<nsIObserver>                 mCharsetMenuObserver;
-  nsCStringArray                        mDecoderList;
+  nsTArray<nsCString>                   mDecoderList;
 
   nsresult Done();
   nsresult SetCharsetCheckmark(nsString * aCharset, PRBool aValue);
 
   nsresult FreeResources();
 
-  nsresult InitStaticMenu(nsCStringArray& aDecs, 
+  nsresult InitStaticMenu(nsTArray<nsCString>& aDecs, 
                           nsIRDFResource * aResource,
                           const char * aKey,
                           nsVoidArray * aArray);
-  nsresult InitCacheMenu(nsCStringArray& aDecs,
+  nsresult InitCacheMenu(nsTArray<nsCString>& aDecs,
                          nsIRDFResource * aResource,
                          const char * aKey,
                          nsVoidArray * aArray);
   
-  nsresult InitMoreMenu(nsCStringArray& aDecs,
+  nsresult InitMoreMenu(nsTArray<nsCString>& aDecs,
                         nsIRDFResource * aResource, 
                         const char * aFlag);
   
-  nsresult InitMoreSubmenus(nsCStringArray& aDecs);
+  nsresult InitMoreSubmenus(nsTArray<nsCString>& aDecs);
 
   static nsresult SetArrayFromEnumerator(nsIUTF8StringEnumerator* aEnumerator,
-                                         nsCStringArray& aArray);
+                                         nsTArray<nsCString>& aArray);
   
   nsresult AddCharsetToItemArray(nsVoidArray* aArray,
                                  const nsAFlatCString& aCharset, 
                                  nsMenuEntry ** aResult,
                                  PRInt32 aPlace);
   nsresult AddCharsetArrayToItemArray(nsVoidArray &aArray, 
-                                      const nsCStringArray& aCharsets);
+                                      const nsTArray<nsCString>& aCharsets);
   nsresult AddMenuItemToContainer(nsIRDFContainer * aContainer, 
     nsMenuEntry * aItem, nsIRDFResource * aType, const char * aIDPrefix, 
     PRInt32 aPlace);
   nsresult AddMenuItemArrayToContainer(nsIRDFContainer * aContainer, 
     nsVoidArray * aArray, nsIRDFResource * aType);
   nsresult AddCharsetToContainer(nsVoidArray * aArray, 
                                  nsIRDFContainer * aContainer,
                                  const nsAFlatCString& aCharset,
                                  const char * aIDPrefix, 
     PRInt32 aPlace, PRInt32 aRDFPlace);
 
   nsresult AddFromPrefsToMenu(nsVoidArray * aArray, 
                               nsIRDFContainer * aContainer,
                               const char * aKey,
-                              nsCStringArray& aDecs,
+                              nsTArray<nsCString>& aDecs,
                               const char * aIDPrefix);
   nsresult AddFromNolocPrefsToMenu(nsVoidArray * aArray, 
                                    nsIRDFContainer * aContainer,
                                    const char * aKey,
-                                   nsCStringArray& aDecs,
+                                   nsTArray<nsCString>& aDecs,
                                    const char * aIDPrefix);
   nsresult AddFromStringToMenu(char * aCharsetList,
                                nsVoidArray * aArray,
                                nsIRDFContainer * aContainer,
-                               nsCStringArray& aDecs,
+                               nsTArray<nsCString>& aDecs,
                                const char * aIDPrefix);
 
   nsresult AddSeparatorToContainer(nsIRDFContainer * aContainer);
   nsresult AddCharsetToCache(const nsAFlatCString& aCharset,
                              nsVoidArray * aArray, 
                              nsIRDFResource * aRDFResource,
                              PRInt32 aCacheStart, PRInt32 aCacheSize, 
                              PRInt32 aRDFPlace);
@@ -277,17 +269,17 @@ private:
     const char * aKey);
   nsresult UpdateCachePrefs(const char * aCacheKey, const char * aCacheSizeKey, 
     const char * aStaticKey, const PRUnichar * aCharset);
 
   nsresult ClearMenu(nsIRDFContainer * aContainer, nsVoidArray * aArray);
   nsresult RemoveLastMenuItem(nsIRDFContainer * aContainer, 
                               nsVoidArray * aArray);
 
-  nsresult RemoveFlaggedCharsets(nsCStringArray& aList, const nsString& aProp);
+  nsresult RemoveFlaggedCharsets(nsTArray<nsCString>& aList, const nsString& aProp);
   nsresult NewRDFContainer(nsIRDFDataSource * aDataSource, 
     nsIRDFResource * aResource, nsIRDFContainer ** aResult);
   void FreeMenuItemArray(nsVoidArray * aArray);
   PRInt32 FindMenuItemInArray(const nsVoidArray* aArray,
                               const nsAFlatCString& aCharset, 
                               nsMenuEntry ** aResult);
   nsresult ReorderMenuItemArray(nsVoidArray * aArray);
   nsresult GetCollation(nsICollation ** aCollation);
@@ -364,35 +356,50 @@ static int CompareMenuItems(const void* 
 
   collation->CompareRawSortKey(rec1->key, rec1->len, rec2->key, rec2->len, &res);
 
   return res;
 }
 
 nsresult
 nsCharsetMenu::SetArrayFromEnumerator(nsIUTF8StringEnumerator* aEnumerator,
-                                      nsCStringArray& aArray)
+                                      nsTArray<nsCString>& aArray)
 {
   nsresult rv;
   
   PRBool hasMore;
   rv = aEnumerator->HasMore(&hasMore);
   
   nsCAutoString value;
   while (NS_SUCCEEDED(rv) && hasMore) {
     rv = aEnumerator->GetNext(value);
     if (NS_SUCCEEDED(rv))
-      aArray.AppendCString(value);
+      aArray.AppendElement(value);
 
     rv = aEnumerator->HasMore(&hasMore);
   }
 
   return rv;
 }
   
+
+class nsIgnoreCaseCStringComparator
+{
+  public:
+    PRBool Equals(const nsACString& a, const nsACString& b) const
+    {
+      return nsCString(a).Equals(b, nsCaseInsensitiveCStringComparator());
+    }
+
+    PRBool LessThan(const nsACString& a, const nsACString& b) const
+    { 
+      return a < b;
+    }
+};
+
 //----------------------------------------------------------------------------
 // Class nsCharsetMenuObserver
 
 class nsCharsetMenuObserver : public nsIObserver {
 
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSIOBSERVER
@@ -578,17 +585,17 @@ nsresult nsCharsetMenu::RefreshBrowserMe
   res = ClearMenu(container, &mBrowserMenu);
   if (NS_FAILED(res)) return res;
 
   // rebuild the menu
   nsCOMPtr<nsIUTF8StringEnumerator> decoders;
   res = mCCManager->GetDecoderList(getter_AddRefs(decoders));
   if (NS_FAILED(res)) return res;
 
-  nsCStringArray decs;
+  nsTArray<nsCString> decs;
   SetArrayFromEnumerator(decoders, decs);
   
   res = AddFromPrefsToMenu(&mBrowserMenu, container, kBrowserStaticPrefKey, 
                            decs, "charset.");
   NS_ASSERTION(NS_SUCCEEDED(res), "error initializing static charset menu from prefs");
 
   // mark the end of the static area, the rest is cache
   mBrowserCacheStart = mBrowserMenu.Count();
@@ -615,17 +622,17 @@ nsresult nsCharsetMenu::RefreshMailviewM
   // clean the menu
   res = ClearMenu(container, &mMailviewMenu);
   if (NS_FAILED(res)) return res;
 
   nsCOMPtr<nsIUTF8StringEnumerator> decoders;
   res = mCCManager->GetDecoderList(getter_AddRefs(decoders));
   if (NS_FAILED(res)) return res;
 
-  nsCStringArray decs;
+  nsTArray<nsCString> decs;
   SetArrayFromEnumerator(decoders, decs);
   
   res = AddFromPrefsToMenu(&mMailviewMenu, container, kMailviewStaticPrefKey, 
                            decs, "charset.");
   NS_ASSERTION(NS_SUCCEEDED(res), "error initializing static charset menu from prefs");
 
   // mark the end of the static area, the rest is cache
   mMailviewCacheStart = mMailviewMenu.Count();
@@ -660,17 +667,17 @@ nsresult nsCharsetMenu::RefreshMaileditM
     NS_ENSURE_SUCCESS(res, res);
   }
 
   // get a list of available encoders
   nsCOMPtr<nsIUTF8StringEnumerator> encoders;
   res = mCCManager->GetEncoderList(getter_AddRefs(encoders));
   NS_ENSURE_SUCCESS(res, res);
 
-  nsCStringArray encs;
+  nsTArray<nsCString> encs;
   SetArrayFromEnumerator(encoders, encs);
   
   // add menu items from pref
   res = AddFromPrefsToMenu(NULL, container, kMaileditPrefKey, encs, NULL);
   NS_ASSERTION(NS_SUCCEEDED(res), "error initializing mailedit charset menu from prefs");
 
   return res;
 }
@@ -686,17 +693,17 @@ nsresult nsCharsetMenu::RefreshComposerM
   // clean the menu
   res = ClearMenu(container, &mComposerMenu);
   if (NS_FAILED(res)) return res;
 
   nsCOMPtr<nsIUTF8StringEnumerator> decoders;
   res = mCCManager->GetDecoderList(getter_AddRefs(decoders));
   if (NS_FAILED(res)) return res;
 
-  nsCStringArray decs;
+  nsTArray<nsCString> decs;
   SetArrayFromEnumerator(decoders, decs);
   
   res = AddFromPrefsToMenu(&mComposerMenu, container, kComposerStaticPrefKey, 
                            decs, "charset.");
   NS_ASSERTION(NS_SUCCEEDED(res), "error initializing static charset menu from prefs");
 
   // mark the end of the static area, the rest is cache
   mComposerCacheStart = mComposerMenu.Count();
@@ -884,18 +891,17 @@ nsresult nsCharsetMenu::InitBrowserMenu(
 
   if (!mBrowserMenuInitialized)  {
     nsCOMPtr<nsIRDFContainer> container;
     res = NewRDFContainer(mInner, kNC_BrowserCharsetMenuRoot, getter_AddRefs(container));
     if (NS_FAILED(res)) return res;
 
 
     // how to clone mDecoderList??
-    nsCStringArray browserDecoderList;
-    CloneCStringArray(mDecoderList, browserDecoderList);
+    nsTArray<nsCString> browserDecoderList = mDecoderList;
 
     res = InitStaticMenu(browserDecoderList, kNC_BrowserCharsetMenuRoot, 
                          kBrowserStaticPrefKey, &mBrowserMenu);
     NS_ASSERTION(NS_SUCCEEDED(res), "error initializing browser static charset menu");
 
     // mark the end of the static area, the rest is cache
     mBrowserCacheStart = mBrowserMenu.Count();
     mPrefs->GetIntPref(kBrowserCacheSizePrefKey, &mBrowserCacheSize);
@@ -944,17 +950,17 @@ nsresult nsCharsetMenu::InitMaileditMenu
     // this would bring in a whole bunch of 'font encoders' as well as genuine 
     // charset encoders, but it's safe because we rely on prefs to filter
     // them out. Moreover, 'customize' menu lists only genuine charset 
     // encoders further guarding  against  'font encoders' sneaking in. 
     nsCOMPtr<nsIUTF8StringEnumerator> encoders;
     res = mCCManager->GetEncoderList(getter_AddRefs(encoders));
     if (NS_FAILED(res))  return res;
 
-    nsCStringArray maileditEncoderList;
+    nsTArray<nsCString> maileditEncoderList;
     SetArrayFromEnumerator(encoders, maileditEncoderList);
   
     res = AddFromPrefsToMenu(NULL, container, kMaileditPrefKey, maileditEncoderList, NULL);
     NS_ASSERTION(NS_SUCCEEDED(res), "error initializing mailedit charset menu from prefs");
 
     // register prefs callback
     nsCOMPtr<nsIPrefBranch2> pbi = do_QueryInterface(mPrefs);
     if (pbi)
@@ -975,18 +981,17 @@ nsresult nsCharsetMenu::InitMailviewMenu
   
   nsresult res = NS_OK;
 
   if (!mMailviewMenuInitialized)  {
     nsCOMPtr<nsIRDFContainer> container;
     res = NewRDFContainer(mInner, kNC_MailviewCharsetMenuRoot, getter_AddRefs(container));
     if (NS_FAILED(res)) return res;
 
-    nsCStringArray mailviewDecoderList;
-    CloneCStringArray(mDecoderList, mailviewDecoderList);
+    nsTArray<nsCString> mailviewDecoderList = mDecoderList;
 
     res = InitStaticMenu(mailviewDecoderList, kNC_MailviewCharsetMenuRoot, 
                          kMailviewStaticPrefKey, &mMailviewMenu);
     NS_ASSERTION(NS_SUCCEEDED(res), "error initializing mailview static charset menu");
 
     // mark the end of the static area, the rest is cache
     mMailviewCacheStart = mMailviewMenu.Count();
     mPrefs->GetIntPref(kMailviewCacheSizePrefKey, &mMailviewCacheSize);
@@ -1017,18 +1022,17 @@ nsresult nsCharsetMenu::InitComposerMenu
  
   nsresult res = NS_OK;
 
   if (!mComposerMenuInitialized)  {
     nsCOMPtr<nsIRDFContainer> container;
     res = NewRDFContainer(mInner, kNC_ComposerCharsetMenuRoot, getter_AddRefs(container));
     if (NS_FAILED(res)) return res;
 
-    nsCStringArray composerDecoderList;
-    CloneCStringArray(mDecoderList, composerDecoderList);
+    nsTArray<nsCString> composerDecoderList = mDecoderList;
 
     // even if we fail, the show must go on
     res = InitStaticMenu(composerDecoderList, kNC_ComposerCharsetMenuRoot, 
       kComposerStaticPrefKey, &mComposerMenu);
     NS_ASSERTION(NS_SUCCEEDED(res), "error initializing composer static charset menu");
 
     // mark the end of the static area, the rest is cache
     mComposerCacheStart = mComposerMenu.Count();
@@ -1056,27 +1060,25 @@ nsresult nsCharsetMenu::InitComposerMenu
 
 nsresult nsCharsetMenu::InitOthers() 
 {
   NS_TIMELINE_START_TIMER("nsCharsetMenu::InitOthers");
 
   nsresult res = NS_OK;
 
   if (!mOthersInitialized) {
-    nsCStringArray othersDecoderList;
-    CloneCStringArray(mDecoderList, othersDecoderList);
+    nsTArray<nsCString> othersDecoderList = mDecoderList;
 
     res = InitMoreMenu(othersDecoderList, kNC_DecodersRoot, ".notForBrowser");                 
     if (NS_FAILED(res))  return res;
 
     // Using mDecoderList instead of GetEncoderList(), we can avoid having to
     // tag a whole bunch of 'font encoders' with '.notForOutgoing' in 
     // charsetData.properties file. 
-    nsCStringArray othersEncoderList;
-    CloneCStringArray(mDecoderList, othersEncoderList);
+    nsTArray<nsCString> othersEncoderList = mDecoderList;
 
     res = InitMoreMenu(othersEncoderList, kNC_EncodersRoot, ".notForOutgoing");                 
     if (NS_FAILED(res)) return res;
   }
 
   mOthersInitialized = NS_SUCCEEDED(res);
 
   NS_TIMELINE_STOP_TIMER("nsCharsetMenu::InitOthers");
@@ -1092,35 +1094,34 @@ nsresult nsCharsetMenu::InitOthers()
  */
 nsresult nsCharsetMenu::InitSecondaryTiers()
 {
   NS_TIMELINE_START_TIMER("nsCharsetMenu::InitSecondaryTiers");
 
   nsresult res = NS_OK;
 
   if (!mSecondaryTiersInitialized)  {
-    nsCStringArray secondaryTiersDecoderList;
-    CloneCStringArray(mDecoderList, secondaryTiersDecoderList);
+    nsTArray<nsCString> secondaryTiersDecoderList = mDecoderList;
 
     res = InitMoreSubmenus(secondaryTiersDecoderList);
     NS_ASSERTION(NS_SUCCEEDED(res), "err init browser charset more submenus");
 
     res = InitMoreMenu(secondaryTiersDecoderList, kNC_BrowserMoreCharsetMenuRoot, ".notForBrowser");
     NS_ASSERTION(NS_SUCCEEDED(res), "err init browser charset more menu");
   }
 
   mSecondaryTiersInitialized = NS_SUCCEEDED(res);
 
   NS_TIMELINE_STOP_TIMER("nsCharsetMenu::InitSecondaryTiers");
   NS_TIMELINE_MARK_TIMER("nsCharsetMenu::InitSecondaryTiers");
 
   return res;
 }
 
-nsresult nsCharsetMenu::InitStaticMenu(nsCStringArray& aDecs,
+nsresult nsCharsetMenu::InitStaticMenu(nsTArray<nsCString>& aDecs,
                                        nsIRDFResource * aResource, 
                                        const char * aKey, 
                                        nsVoidArray * aArray)
 {
   NS_TIMELINE_START_TIMER("nsCharsetMenu::InitStaticMenu");
 
   nsresult res = NS_OK;
   nsCOMPtr<nsIRDFContainer> container;
@@ -1137,17 +1138,17 @@ nsresult nsCharsetMenu::InitStaticMenu(n
 
   NS_TIMELINE_STOP_TIMER("nsCharsetMenu::InitStaticMenu");
   NS_TIMELINE_MARK_TIMER("nsCharsetMenu::InitStaticMenu");
 
   return res;
 }
 
 nsresult nsCharsetMenu::InitCacheMenu(
-                        nsCStringArray& aDecs,
+                        nsTArray<nsCString>& aDecs,
                         nsIRDFResource * aResource, 
                         const char * aKey, 
                         nsVoidArray * aArray)
 {
   NS_TIMELINE_START_TIMER("nsCharsetMenu::InitCacheMenu");
 
   nsresult res = NS_OK;
   nsCOMPtr<nsIRDFContainer> container;
@@ -1168,17 +1169,17 @@ nsresult nsCharsetMenu::InitAutodetMenu(
 {
   NS_TIMELINE_START_TIMER("nsCharsetMenu::InitAutodetMenu");
 
   nsresult res = NS_OK;
 
   if (!mAutoDetectInitialized) {
     nsVoidArray chardetArray;
     nsCOMPtr<nsIRDFContainer> container;
-    nsCStringArray detectorArray;
+    nsTArray<nsCString> detectorArray;
 
     res = NewRDFContainer(mInner, kNC_BrowserAutodetMenuRoot, getter_AddRefs(container));
     if (NS_FAILED(res)) return res;
 
     nsCOMPtr<nsIUTF8StringEnumerator> detectors;
     res = mCCManager->GetCharsetDetectorList(getter_AddRefs(detectors));
     if (NS_FAILED(res)) goto done;
 
@@ -1204,17 +1205,17 @@ nsresult nsCharsetMenu::InitAutodetMenu(
   mAutoDetectInitialized = NS_SUCCEEDED(res);
 
   NS_TIMELINE_STOP_TIMER("nsCharsetMenu::InitAutodetMenu");
   NS_TIMELINE_MARK_TIMER("nsCharsetMenu::InitAutodetMenu");
 
   return res;
 }
 
-nsresult nsCharsetMenu::InitMoreMenu(nsCStringArray& aDecs, 
+nsresult nsCharsetMenu::InitMoreMenu(nsTArray<nsCString>& aDecs, 
                                      nsIRDFResource * aResource, 
                                      const char * aFlag)
 {
   NS_TIMELINE_START_TIMER("nsCharsetMenu::InitMoreMenu");
 
   nsresult res = NS_OK;
   nsCOMPtr<nsIRDFContainer> container;
   nsVoidArray moreMenu;
@@ -1242,17 +1243,17 @@ done:
 
   NS_TIMELINE_STOP_TIMER("nsCharsetMenu::InitMoreMenu");
   NS_TIMELINE_MARK_TIMER("nsCharsetMenu::InitMoreMenu");
 
   return res;
 }
 
 // XXX please make this method more general; the cut&pasted code is laughable
-nsresult nsCharsetMenu::InitMoreSubmenus(nsCStringArray& aDecs)
+nsresult nsCharsetMenu::InitMoreSubmenus(nsTArray<nsCString>& aDecs)
 {
   NS_TIMELINE_START_TIMER("nsCharsetMenu::InitMoreSubmenus");
 
   nsresult res = NS_OK;
 
   nsCOMPtr<nsIRDFContainer> container1;
   nsCOMPtr<nsIRDFContainer> container2;
   nsCOMPtr<nsIRDFContainer> container3;
@@ -1343,28 +1344,27 @@ nsresult nsCharsetMenu::AddCharsetToItem
 done:
   if (item != NULL) delete item;
 
   return res;
 }
 
 nsresult
 nsCharsetMenu::AddCharsetArrayToItemArray(nsVoidArray& aArray, 
-                                          const nsCStringArray& aCharsets) 
+                                          const nsTArray<nsCString>& aCharsets) 
 {
-  PRUint32 count = aCharsets.Count();
+  PRUint32 count = aCharsets.Length();
 
   for (PRUint32 i = 0; i < count; i++) {
 
-    nsCString* str = aCharsets.CStringAt(i);
-    if (str) {
-      nsresult res = AddCharsetToItemArray(&aArray, *str, NULL, -1);
+    const nsCString& str = aCharsets[i];
+    nsresult res = AddCharsetToItemArray(&aArray, str, NULL, -1);
     
-      if (NS_FAILED(res)) return res;
-    }
+    if (NS_FAILED(res))
+      return res;
   }
 
   return NS_OK;
 }
 
 // aPlace < -1 for Remove
 // aPlace < 0 for Append
 nsresult nsCharsetMenu::AddMenuItemToContainer(
@@ -1469,17 +1469,17 @@ done:
 
   return res;
 }
 
 nsresult nsCharsetMenu::AddFromPrefsToMenu(
                         nsVoidArray * aArray, 
                         nsIRDFContainer * aContainer, 
                         const char * aKey, 
-                        nsCStringArray& aDecs, 
+                        nsTArray<nsCString>& aDecs, 
                         const char * aIDPrefix)
 {
   nsresult res = NS_OK;
 
   nsCOMPtr<nsIPrefLocalizedString> pls;
   res = mPrefs->GetComplexValue(aKey, NS_GET_IID(nsIPrefLocalizedString), getter_AddRefs(pls));
   if (NS_FAILED(res)) return res;
 
@@ -1494,17 +1494,17 @@ nsresult nsCharsetMenu::AddFromPrefsToMe
 
   return res;
 }
 
 nsresult
 nsCharsetMenu::AddFromNolocPrefsToMenu(nsVoidArray * aArray, 
                                        nsIRDFContainer * aContainer, 
                                        const char * aKey, 
-                                       nsCStringArray& aDecs, 
+                                       nsTArray<nsCString>& aDecs, 
                                        const char * aIDPrefix)
 {
   nsresult res = NS_OK;
 
   char * value = NULL;
   res = mPrefs->GetCharPref(aKey, &value);
   if (NS_FAILED(res)) return res;
 
@@ -1515,40 +1515,39 @@ nsCharsetMenu::AddFromNolocPrefsToMenu(n
 
   return res;
 }
 
 nsresult nsCharsetMenu::AddFromStringToMenu(
                         char * aCharsetList, 
                         nsVoidArray * aArray, 
                         nsIRDFContainer * aContainer, 
-                        nsCStringArray& aDecs, 
+                        nsTArray<nsCString>& aDecs, 
                         const char * aIDPrefix)
 {
   nsresult res = NS_OK;
   char * p = aCharsetList;
   char * q = p;
   while (*p != 0) {
 	  for (; (*q != ',') && (*q != ' ') && (*q != 0); q++) {;}
     char temp = *q;
     *q = 0;
 
     // if this charset is not on the accepted list of charsets, ignore it
     PRInt32 index;
-    index = aDecs.IndexOfIgnoreCase(nsCAutoString(p));
+    index = aDecs.IndexOf(nsCAutoString(p), 0, nsIgnoreCaseCStringComparator());
     if (index >= 0) {
 
       // else, add it to the menu
       res = AddCharsetToContainer(aArray, aContainer, nsDependentCString(p),
                                   aIDPrefix, -1, 0);
       NS_ASSERTION(NS_SUCCEEDED(res), "cannot add charset to menu");
       if (NS_FAILED(res)) break;
 
-      res = aDecs.RemoveCStringAt(index);
-      NS_ASSERTION(NS_SUCCEEDED(res), "cannot remove atom from array");
+      aDecs.RemoveElementAt(index);
     }
 
     *q = temp;
     for (; (*q == ',') || (*q == ' '); q++) {;}
     p=q;
   }
 
   return NS_OK;
@@ -1699,36 +1698,32 @@ nsresult nsCharsetMenu::RemoveLastMenuIt
       res = aArray->RemoveElementAt(last);
       if (NS_FAILED(res)) return res;
     }
   }
 
   return res;
 }
 
-nsresult nsCharsetMenu::RemoveFlaggedCharsets(nsCStringArray& aList, 
+nsresult nsCharsetMenu::RemoveFlaggedCharsets(nsTArray<nsCString>& aList, 
                                               const nsString& aProp)
 {
   nsresult res = NS_OK;
   PRUint32 count;
 
-  count = aList.Count();
+  count = aList.Length();
   if (NS_FAILED(res)) return res;
 
-  nsCString* charset;
   nsAutoString str;
   for (PRUint32 i = 0; i < count; i++) {
 
-    charset = aList.CStringAt(i);
-    if (!charset) continue;
-
-    res = mCCManager->GetCharsetData(charset->get(), aProp.get(), str);
+    res = mCCManager->GetCharsetData(aList[i].get(), aProp.get(), str);
     if (NS_FAILED(res)) continue;
 
-    aList.RemoveCStringAt(i);
+    aList.RemoveElementAt(i);
 
     i--; 
     count--;
   }
 
   return NS_OK;
 }