diff --git a/mozilla/intl/uconv/src/nsCharsetAliasImp.cpp b/mozilla/intl/uconv/src/nsCharsetAliasImp.cpp index 82bd2b1e38c..821f62603c1 100644 --- a/mozilla/intl/uconv/src/nsCharsetAliasImp.cpp +++ b/mozilla/intl/uconv/src/nsCharsetAliasImp.cpp @@ -63,6 +63,16 @@ nsCharsetAlias2::~nsCharsetAlias2() if(mDelegate) delete mDelegate; } + +// +static const char* kAliases[][3] = { + // Triple with { lower-case test string, out string, length of out string } + { "iso-8859-1", "ISO-8859-1", (const char*)10 }, + { "utf-8", "UTF-8", (const char*)5 }, + { "x-sjis", "Shift_JIS", (const char*)9 }, + { "shift_jis", "Shift_JIS", (const char*)9 } +}; + //-------------------------------------------------------------- NS_IMETHODIMP nsCharsetAlias2::GetPreferred(const nsACString& aAlias, nsACString& oResult) @@ -70,35 +80,26 @@ NS_IMETHODIMP nsCharsetAlias2::GetPreferred(const nsACString& aAlias, if (aAlias.IsEmpty()) return NS_ERROR_NULL_POINTER; NS_TIMELINE_START_TIMER("nsCharsetAlias2:GetPreferred"); - nsCAutoString aKey(aAlias); - ToLowerCase(aKey); - oResult.Truncate(); // Delay loading charsetalias.properties by hardcoding the most // frequent aliases. Note that it's possible to recur in to this // function *while loading* charsetalias.properties (see bug 190951), // so we might have an |mDelegate| already that isn't valid yet, but // the load is guaranteed to be "UTF-8" so things will be OK. - if(aKey.EqualsLiteral("utf-8")) { - oResult.AssignLiteral("UTF-8"); - NS_TIMELINE_STOP_TIMER("nsCharsetAlias2:GetPreferred"); - return NS_OK; - } - if(aKey.EqualsLiteral("iso-8859-1")) { - oResult.AssignLiteral("ISO-8859-1"); - NS_TIMELINE_STOP_TIMER("nsCharsetAlias2:GetPreferred"); - return NS_OK; - } - if(aKey.EqualsLiteral("x-sjis") || - aKey.EqualsLiteral("shift_jis")) { - oResult.AssignLiteral("Shift_JIS"); - NS_TIMELINE_STOP_TIMER("nsCharsetAlias2:GetPreferred"); - return NS_OK; - } + for (PRUint32 index = 0; index < NS_ARRAY_LENGTH(kAliases); index++) { + if (aAlias.LowerCaseEqualsASCII(kAliases[index][0])) { + oResult.Assign(nsDependentCString(kAliases[index][1], + (PRUint32)kAliases[index][2])); + NS_TIMELINE_STOP_TIMER("nsCharsetAlias2:GetPreferred"); + return NS_OK; + } + } + + oResult.Truncate(); if(!mDelegate) { //load charsetalias.properties string bundle with all remaining aliases - // we may need to protect the following section with a lock so we won't call the + // we may need to protect the following section with a lock so we won't call the // 'new nsGREResProperties' from two different threads mDelegate = new nsGREResProperties( NS_LITERAL_CSTRING("charsetalias.properties") ); NS_ASSERTION(mDelegate, "cannot create nsGREResProperties"); @@ -109,10 +110,13 @@ NS_IMETHODIMP nsCharsetAlias2::GetPreferred(const nsACString& aAlias, NS_TIMELINE_STOP_TIMER("nsCharsetAlias2:GetPreferred"); NS_TIMELINE_MARK_TIMER("nsCharsetAlias2:GetPreferred"); + nsCAutoString key(aAlias); + ToLowerCase(key); + // hack for now, have to fix nsGREResProperties, but we can't until // string bundles use UTF8 keys nsAutoString result; - nsresult rv = mDelegate->Get(NS_ConvertASCIItoUTF16(aKey), result); + nsresult rv = mDelegate->Get(NS_ConvertASCIItoUTF16(key), result); LossyAppendUTF16toASCII(result, oResult); return rv; } diff --git a/mozilla/intl/uconv/src/nsCharsetConverterManager.cpp b/mozilla/intl/uconv/src/nsCharsetConverterManager.cpp index 5fd364e4a89..5b2dc368abd 100644 --- a/mozilla/intl/uconv/src/nsCharsetConverterManager.cpp +++ b/mozilla/intl/uconv/src/nsCharsetConverterManager.cpp @@ -86,6 +86,12 @@ nsCharsetConverterManager::~nsCharsetConverterManager() NS_IF_RELEASE(mTitleBundle); } +nsresult nsCharsetConverterManager::Init() +{ + if (!mDecoderHash.Init()) + return NS_ERROR_OUT_OF_MEMORY; + return NS_OK; +} nsresult nsCharsetConverterManager::RegisterConverterManagerData() { @@ -254,30 +260,28 @@ nsCharsetConverterManager::GetUnicodeDecoderRaw(const char * aSrc, #endif nsresult rv = NS_OK; - NS_NAMED_LITERAL_CSTRING(kUnicodeDecoderContractIDBase, - NS_UNICODEDECODER_CONTRACTID_BASE); - - nsCAutoString contractid(kUnicodeDecoderContractIDBase + - nsDependentCString(aSrc)); - - if (!strncmp(aSrc, - NS_1BYTE_CODER_PATTERN, - NS_1BYTE_CODER_PATTERN_LEN)) + NS_NAMED_LITERAL_CSTRING(contractbase, NS_UNICODEDECODER_CONTRACTID_BASE); + nsDependentCString src(aSrc); + + if (!strncmp(aSrc, NS_1BYTE_CODER_PATTERN, NS_1BYTE_CODER_PATTERN_LEN)) { - // Single byte decoders dont hold state. Optimize by using a service. - decoder = do_GetService(contractid.get(), &rv); + // Single byte decoders don't hold state. Optimize by using a service, and + // cache it in our hash to avoid repeated trips through the service manager. + if (!mDecoderHash.Get(aSrc, getter_AddRefs(decoder))) { + decoder = do_GetService(PromiseFlatCString(contractbase + src).get(), + &rv); + if (NS_SUCCEEDED(rv)) + mDecoderHash.Put(aSrc, decoder); + } } else { - decoder = do_CreateInstance(contractid.get(), &rv); - } - if(NS_FAILED(rv)) - rv = NS_ERROR_UCONV_NOCONV; - else - { - *aResult = decoder.get(); - NS_ADDREF(*aResult); + decoder = do_CreateInstance(PromiseFlatCString(contractbase + src).get(), + &rv); } + NS_ENSURE_SUCCESS(rv, NS_ERROR_UCONV_NOCONV); + + decoder.forget(aResult); return rv; } diff --git a/mozilla/intl/uconv/src/nsCharsetConverterManager.h b/mozilla/intl/uconv/src/nsCharsetConverterManager.h index fa7e3532545..21fcd7a2558 100644 --- a/mozilla/intl/uconv/src/nsCharsetConverterManager.h +++ b/mozilla/intl/uconv/src/nsCharsetConverterManager.h @@ -40,6 +40,7 @@ #include "nsISupports.h" #include "nsICharsetConverterManager.h" #include "nsIStringBundle.h" +#include "nsInterfaceHashtable.h" #ifdef MOZ_USE_NATIVE_UCONV #include "nsINativeUConvService.h" @@ -55,6 +56,8 @@ public: nsCharsetConverterManager(); virtual ~nsCharsetConverterManager(); + nsresult Init(); + private: nsIStringBundle * mDataBundle; @@ -64,6 +67,8 @@ private: nsCOMPtr mNativeUC; #endif + nsInterfaceHashtable mDecoderHash; + nsresult LoadExtensibleBundle(const char * aRegistryKey, nsIStringBundle ** aResult); diff --git a/mozilla/intl/uconv/src/nsUConvModule.cpp b/mozilla/intl/uconv/src/nsUConvModule.cpp index ac214f23159..d9a72788099 100644 --- a/mozilla/intl/uconv/src/nsUConvModule.cpp +++ b/mozilla/intl/uconv/src/nsUConvModule.cpp @@ -610,7 +610,7 @@ nsConverterManagerDataRegister(nsIComponentManager* aCompMgr, return nsCharsetConverterManager::RegisterConverterManagerData(); } -NS_GENERIC_FACTORY_CONSTRUCTOR(nsCharsetConverterManager) +NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsCharsetConverterManager, Init) NS_GENERIC_FACTORY_CONSTRUCTOR(nsTextToSubURI) NS_GENERIC_FACTORY_CONSTRUCTOR(nsUTF8ConverterService) NS_GENERIC_FACTORY_CONSTRUCTOR(nsCharsetAlias2) diff --git a/mozilla/parser/htmlparser/src/nsParser.cpp b/mozilla/parser/htmlparser/src/nsParser.cpp index b52fc972dae..e2badf87525 100644 --- a/mozilla/parser/htmlparser/src/nsParser.cpp +++ b/mozilla/parser/htmlparser/src/nsParser.cpp @@ -48,6 +48,7 @@ #include "nsICachingChannel.h" #include "nsICacheEntryDescriptor.h" #include "nsICharsetAlias.h" +#include "nsICharsetConverterManager.h" #include "nsIInputStream.h" #include "CNavDTD.h" #include "prenv.h" @@ -154,6 +155,9 @@ public: //-------------- End ParseContinue Event Definition ------------------------ +nsICharsetAlias* nsParser::sCharsetAliasService = nsnull; +nsICharsetConverterManager* nsParser::sCharsetConverterManager = nsnull; + /** * This gets called when the htmlparser module is initialized. */ @@ -204,6 +208,17 @@ nsParser::Init() } } + nsCOMPtr charsetAlias = + do_GetService(NS_CHARSETALIAS_CONTRACTID, &rv); + NS_ENSURE_SUCCESS(rv, rv); + + nsCOMPtr charsetConverter = + do_GetService(NS_CHARSETCONVERTERMANAGER_CONTRACTID, &rv); + NS_ENSURE_SUCCESS(rv, rv); + + charsetAlias.swap(sCharsetAliasService); + charsetConverter.swap(sCharsetConverterManager); + return NS_OK; } @@ -216,9 +231,11 @@ void nsParser::Shutdown() { delete sParserDataListeners; sParserDataListeners = nsnull; + + NS_IF_RELEASE(sCharsetAliasService); + NS_IF_RELEASE(sCharsetConverterManager); } - #ifdef DEBUG static PRBool gDumpContent=PR_FALSE; #endif diff --git a/mozilla/parser/htmlparser/src/nsParser.h b/mozilla/parser/htmlparser/src/nsParser.h index 09c326cae46..e77bb0f0605 100644 --- a/mozilla/parser/htmlparser/src/nsParser.h +++ b/mozilla/parser/htmlparser/src/nsParser.h @@ -90,6 +90,8 @@ #include "nsIUnicharStreamListener.h" #include "nsCycleCollectionParticipant.h" +class nsICharsetConverterManager; +class nsICharsetAlias; class nsIDTD; class nsScanner; class nsIProgressEventSink; @@ -124,7 +126,6 @@ class nsParser : public nsIParser, */ nsParser(); - /** * Destructor * @update gess5/11/98 @@ -372,6 +373,14 @@ class nsParser : public nsIParser, static nsCOMArray *sParserDataListeners; + static nsICharsetAlias* GetCharsetAliasService() { + return sCharsetAliasService; + } + + static nsICharsetConverterManager* GetCharsetConverterManager() { + return sCharsetConverterManager; + } + protected: /** @@ -455,7 +464,8 @@ protected: nsCString mCharset; nsCString mCommandStr; - + static nsICharsetAlias* sCharsetAliasService; + static nsICharsetConverterManager* sCharsetConverterManager; public: diff --git a/mozilla/parser/htmlparser/src/nsScanner.cpp b/mozilla/parser/htmlparser/src/nsScanner.cpp index 45f2d3c8ada..1325f49ff16 100644 --- a/mozilla/parser/htmlparser/src/nsScanner.cpp +++ b/mozilla/parser/htmlparser/src/nsScanner.cpp @@ -103,7 +103,6 @@ nsScanner::nsScanner(const nsAString& anHTMLString, const nsACString& aCharset, mIncremental = PR_FALSE; mUnicodeDecoder = 0; mCharsetSource = kCharsetUninitialized; - SetDocumentCharset(aCharset, aSource); } /** @@ -149,42 +148,48 @@ nsresult nsScanner::SetDocumentCharset(const nsACString& aCharset , PRInt32 aSou if( aSource < mCharsetSource) // priority is lower the the current one , just return res; - nsCOMPtr calias(do_GetService(NS_CHARSETALIAS_CONTRACTID, &res)); - NS_ASSERTION( nsnull != calias, "cannot find charset alias"); - if( NS_SUCCEEDED(res) && (nsnull != calias)) + nsICharsetAlias* calias = nsParser::GetCharsetAliasService(); + NS_ASSERTION(calias, "Must have the charset alias service!"); + + if (!mCharset.IsEmpty()) { - PRBool same = PR_FALSE; + PRBool same; res = calias->Equals(aCharset, mCharset, &same); if(NS_SUCCEEDED(res) && same) { return NS_OK; // no difference, don't change it } - // different, need to change it - nsCAutoString charsetName; - res = calias->GetPreferred(aCharset, charsetName); - - if(NS_FAILED(res) && (kCharsetUninitialized == mCharsetSource) ) - { - // failed - unknown alias , fallback to ISO-8859-1 - charsetName.AssignLiteral("ISO-8859-1"); - } - mCharset = charsetName; - mCharsetSource = aSource; - - nsCOMPtr ccm = - do_GetService(NS_CHARSETCONVERTERMANAGER_CONTRACTID, &res); - if(NS_SUCCEEDED(res) && (nsnull != ccm)) - { - nsIUnicodeDecoder * decoder = nsnull; - res = ccm->GetUnicodeDecoderRaw(mCharset.get(), &decoder); - if(NS_SUCCEEDED(res) && (nsnull != decoder)) - { - NS_IF_RELEASE(mUnicodeDecoder); - - mUnicodeDecoder = decoder; - } - } } + + // different, need to change it + nsCString charsetName; + res = calias->GetPreferred(aCharset, charsetName); + + if(NS_FAILED(res) && (mCharsetSource == kCharsetUninitialized)) + { + // failed - unknown alias , fallback to ISO-8859-1 + mCharset.AssignLiteral("ISO-8859-1"); + } + else + { + mCharset.Assign(charsetName); + } + + mCharsetSource = aSource; + + NS_ASSERTION(nsParser::GetCharsetConverterManager(), + "Must have the charset converter manager!"); + + nsIUnicodeDecoder * decoder = nsnull; + res = nsParser::GetCharsetConverterManager()-> + GetUnicodeDecoderRaw(mCharset.get(), &decoder); + if(NS_SUCCEEDED(res) && (nsnull != decoder)) + { + NS_IF_RELEASE(mUnicodeDecoder); + + mUnicodeDecoder = decoder; + } + return res; }